据我所知,Tk按键和键释放事件只能在按键实际按下或释放时触发?
但是,使用以下简单代码,如果我按住"a"键,我将获得连续按键/键释放事件的连续序列.
我做错了什么还是TkInter越野车?这是关于Linux的Python2.7.
from Tkinter import *
def keyup(e):
print 'up', e.char
def keydown(e):
print 'down', e.char
root = Tk()
frame = Frame(root, width=100, height=100)
frame.bind("<KeyPress>", keydown)
frame.bind("<KeyRelease>", keyup)
frame.pack()
frame.focus_set()
root.mainloop()
Run Code Online (Sandbox Code Playgroud)
按住"a"时输出:
down a
up a
down a
up a
down a
up a
down a
up a
etc...
Run Code Online (Sandbox Code Playgroud)
los*_*ost 18
好的一些研究发现这个有用的帖子显示这是由于X的自动重复行为而发生的.您可以使用禁用此功能
os.system('xset r off')
Run Code Online (Sandbox Code Playgroud)
然后使用脚本末尾的"on"重置它.问题是这是全局行为 - 不只是我的脚本 - 这不是很好,所以我希望有人能想出更好的方法.
好吧,现在有点晚了,但我有一个可行的解决方案。这不是很好,但它不需要 os.system 覆盖系统设置,这很好。
基本上,我创建了一个记录按键时间的类。我说当某个键在最后很短的时间内(此处为 0.1 毫秒)被按下时,该键已被按下。要获得按下,很简单:如果按键未注册为按下,则触发事件。对于释放,逻辑更难:如果存在可疑的释放事件,请设置一个短时间的计时器(此处为 0.1 秒),然后检查以确保按键没有按下。
验证按下或释放后,请在代码中调用 on_key_press 或 on_key_release 方法。至于那些,只需按照您最初想要的方式实现即可
我知道这并不完美,但我希望它能有所帮助!
这是代码:
初始化按键事件的位置:
key_tracker = KeyTracker()
window.bind_all('<KeyPress>', key_tracker.report_key_press)
window.bind_all('<KeyRelease>', key_tracker.report_key_release)
key_tracker.track('space')
Run Code Online (Sandbox Code Playgroud)
这是我的自定义 KeyTracker 类:
class KeyTracker():
key = ''
last_press_time = 0
last_release_time = 0
def track(self, key):
self.key = key
def is_pressed(self):
return time.time() - self.last_press_time < .1
def report_key_press(self, event):
if event.keysym == self.key:
if not self.is_pressed():
on_key_press(event)
self.last_press_time = time.time()
def report_key_release(self, event):
if event.keysym == self.key:
timer = threading.Timer(.1, self.report_key_release_callback, args=[event])
timer.start()
def report_key_release_callback(self, event):
if not self.is_pressed():
on_key_release(event)
self.last_release_time = time.time()
Run Code Online (Sandbox Code Playgroud)
自动重复行为取决于系统。在Win7中,
down a
down a
down a
...
down a
up a
Run Code Online (Sandbox Code Playgroud)
这是不到一秒钟。