我可以得到在键盘上按下一个键的时间量吗
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 中做到这一点。你能给我一些开始的链接吗?以上是关于我可以得到在键盘上按下一个键的时间量吗的主要内容,如果未能解决你的问题,请参考以下文章