我可以得到在键盘上按下一个键的时间量吗

Posted

技术标签:

【中文标题】我可以得到在键盘上按下一个键的时间量吗【英文标题】:Can I get the amount of time for which a key is pressed on a keyboard 【发布时间】:2010-04-28 00:55:44 【问题描述】:

我正在开展一个项目,我必须根据用户的击键风格开发生物密码。 假设用户输入密码 20 次,他的击键被记录下来,比如

holdtime :按下特定键的时间。 digraph time : 按下不同键所需的时间。

假设用户键入密码“COMPUTER”。我需要知道每个键被按下的时间。类似:

上述密码的保留时间为

C-- 200ms O-- 130ms M-- 150ms P-- 175ms U-- 320ms T-- 230ms E-- 120ms R-- 300ms

这背后的原因是,每个用户都有不同的保持时间。假设一个老人正在输入密码,他会比一个学生花费更多的时间。它对特定的人来说是独一无二的。 为了做这个项目,我需要记录每个按键按下的时间。 如果有人能指导我如何获得这些时间,我将不胜感激。

从这里编辑.. 语言并不重要,但我更喜欢用 C 语言。我对获取数据集更感兴趣。

【问题讨论】:

您的标签有些混乱...您希望在什么语言中使用它以及在什么操作系统上使用? 嗨,乔治,感谢您的回复。我更喜欢它在 C 或 C++ 中。我对获取数据集更感兴趣。 你用什么操作系统来做这个... Linux?如果是这样,您使用的是什么窗口管理器/桌面环境? 我正在使用的操作系统的详细信息:2.6.31-18-generic #55-Ubuntu SMP Fri Jan 8 14:55:26 UTC 2010 i686 GNU/Linux 我在 Vaio 笔记本电脑上做。所以它是一个 QWERTY 键盘。 好的... Ubuntu 默认使用 gnome 桌面环境,所以也许您可以考虑使用 GTK 应用程序捕获按键事件?还是必须在终端中? 【参考方案1】:

记录 KeyDown 和 KeyUp 事件,并对每个事件的时间戳进行比较。

http://code.activestate.com/recipes/203830/

编辑: 您可能想查看 wxPython,它应该可以帮助您:

http://www.wxpython.org/onlinedocs.php

特别是:

http://docs.wxwidgets.org/stable/wx_wxkeyevent.html#wxkeyevent

【讨论】:

嗨,我尝试运行代码,但我不明白它是如何工作的,它在终端上给出了一些无限循环的数字。如果您能提供一些进一步的指导,我将不胜感激。【参考方案2】:

你提到你更喜欢在 C 中使用它,但是因为你将它标记为 Python...:)

另外,既然您说您正在寻找构建数据集,我假设您必须邀请用户输入任意文本,因此您需要某种界面(图形或其他方式)。

这是一个使用 pygame 的简单示例。您可以对其进行简单的修改以要求用户输入特定的单词,但实际上,它只会让用户输入任意文本,记录所有按键的按下时间,并按以下顺序打印每个保持和二合字母时间用户在退出时(即用户按 Esc 时)键入它。

Kibibu 注意到,实时向用户显示他正在输入的内容会引入延迟,这可能会掩盖实际的按键时间,因此此代码仅显示用户在输入“Enter”时输入的内容。

更新:它现在计算有向图和保持时间(在这两种情况下都不包括 Enter)。

更新 2:根据 Adi 的要求,从显示平均值更改为按顺序显示每个单独的时间。

import sys
from collections import defaultdict
from time import time
import pygame
from pygame.key import name as keyname
from pygame.locals import *

# Mapping of a key to a list of holdtimes (from which you can average, etc)
holdtimes = defaultdict(list)
# Mapping of a key pair to a list of digraph times
digraphs = defaultdict(list)
# Keys which have been pressed down, but not up yet.
pending = 
# Last key to be de-pressed, corresponding time).
last_key = None
# Text that the user has typed so far (one sublist for every Enter pressed)
typed_text = [[]]

def show_times():
    all_text = [k for line in typed_text for k in line]
    print "Holdtimes:"
    for key in all_text:
        print "%s: %.5f" % (key, holdtimes[key].pop(0))

    print "Digraphs:"
    for key1, key2 in zip(all_text, all_text[1:]):
        print "(%s, %s): %.5f" % (key1, key2,
                                  digraphs[(key1, key2)].pop(0))

def time_keypresses(events):
    global last_key
    for event in events:
        if event.type == KEYDOWN:
            # ESC exits the program
            if event.key == K_ESCAPE:
                show_times()
                sys.exit(0)

            t = pending[event.key] = time()
            if last_key is not None:
                if event.key != K_RETURN:
                    digraphs[(last_key[0], keyname(event.key))].append(t - last_key[1])
                last_key = None
        elif event.type == KEYUP:
            if event.key == K_RETURN:
                update_screen()
                typed_text.append([])
                pending.pop(event.key)
                last_key = None
            else:
                t = time()
                holdtimes[keyname(event.key)].append(t - pending.pop(event.key))
                last_key = [keyname(event.key), t]
                typed_text[-1].append(keyname(event.key))
        # Any other event handling you might have would go here...

def update_screen():
    global screen
    screen.fill((255, 255, 255))

    header_font = pygame.font.Font(None, 42)
    header = header_font.render("Type away! Press 'Enter' to show.", True, (0, 0, 0))
    header_rect = header.get_rect()
    header_rect.centerx = screen.get_rect().centerx
    header_rect.centery = screen.get_rect().centery - 100

    text_font = pygame.font.Font(None, 32)
    user_text = text_font.render("".join(typed_text[-1]) if typed_text[-1] else "...",
                                 True, (0, 0, 255))
    text_rect = user_text.get_rect()
    text_rect.centerx = screen.get_rect().centerx
    text_rect.centery = screen.get_rect().centery    

    screen.blit(header, header_rect)
    screen.blit(user_text, text_rect)

    pygame.display.update()


if __name__ == '__main__':
    pygame.init()
    window = pygame.display.set_mode((800, 600))
    screen = pygame.display.get_surface()
    update_screen()
    while True:
        time_keypresses(pygame.event.get())

【讨论】:

糟糕,抱歉,我不小心发了两次。我删除了错误的条目。 这会产生什么样的时间分辨率?我建议将屏幕更新与事件循环分离,这样所有的 blitting 都不会降低您的计时器准确性(就像这个屏幕更新可能以 10000 赫兹运行一样微不足道,但仍然......) 你确定你发布了整个代码,我认为有些部分丢失了 Kibibu:是的,在我发布我的原始答案后我就想到了。我更新了脚本,只显示用户每次按 Enter 时最后输入的内容。这应该可以避免屏幕更新延迟,代价是用户无法实时看到他输入的内容。 Berkay:我很确定,我是直接从 Emacs 复制过来的。我刚刚更新了代码,请再次检查,如果您在运行此代码时仍然遇到问题,请告诉我。【参考方案3】:

看看ncurses。这是获取终端中按键信息的绝佳工具。

也请查看this 链接。

【讨论】:

感谢乔治的回复。我看到我可以使用 Ncurses 来知道按下的键,我也可以用它来知道 keyup 和 keydown 时间并取差来获取保持键时间吗? 那么您可以做的是获取按下键时的系统时间和释放键时的系统时间。然后减去差值得到密钥的保持时间。 哦,你的意思是,我可以使用 gettimeofday 之类的方法记下时间,然后减去它。谢谢您的提示,我会尝试并回复您。。【参考方案4】:

如果您以锥形模式从终端读取,则可以在按下时读取每个按键。你不会看到 keydown keyup 事件,就像你捕获 X 事件时那样,但它可能更容易,特别是如果你只是在控制台或终端中运行。

【讨论】:

【参考方案5】:

答案是有条件的“是”。

如果您的语言/环境具有提供 Key-Down 和 Key-Up 事件的交互式键盘支持,那么您可以同时捕获事件和它们之间的时间差。

这在网页上的 javascript 中将非常简单,这也是向更广泛的受众展示您的作品的最简单方法。

【讨论】:

感谢 Dkamins,非常感谢您的评论。我想知道如何在 Javascript 中做到这一点。你能给我一些开始的链接吗?

以上是关于我可以得到在键盘上按下一个键的时间量吗的主要内容,如果未能解决你的问题,请参考以下文章

C# - 在键盘上按下两个按钮后准备事件[重复]

如何在 QT 虚拟键盘上按下信号键并播放声音点击轨道?

在 mfc 应用程序中捕获键盘上按下的键

在科尔多瓦的键盘上按下“完成”按钮时调用一个函数[重复]

当我在 Swift 上按下搜索栏时如何使键盘消失?

禁用iPhone 4S /新iPad键盘上的听写按钮