Python TkInter 按键、按键释放事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27215326/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
TkInter keypress, keyrelease events
提问by lost
I understood that the Tk keypress and keyrelease events were supposed only to fire when the key was actually pressed or released?
我知道 Tk keypress 和 keyrelease 事件应该只在实际按下或释放键时触发?
However with the following simple code, if I hold down the "a" key I get a continual sequence of alternating keypress/keyrelease events.
但是,通过下面的简单代码,如果我按住“a”键,我会得到一个连续的按键/按键释放事件交替序列。
Am I doing something wrong or is TkInter buggy? This is Python2.7 on Linux mint.
我做错了什么还是 TkInter 有问题?这是 Linux mint 上的 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()
Output when pressing and holding "a":
按住“a”时的输出:
down a
up a
down a
up a
down a
up a
down a
up a
etc...
回答by lost
Ok some more research found this helpful postwhich shows this is occuring because of X's autorepeat behaviour. You can disable this by using
好的,更多的研究发现这个有用的帖子表明这是由于 X 的自动重复行为而发生的。您可以使用禁用此功能
os.system('xset r off')
and then reset it using "on" at the end of your script. The problem is this is global behaviour - not just my script - which isn't great so I'm hoping someone can come up with a better way.
然后在脚本末尾使用“on”重置它。问题是这是全局行为 - 不仅仅是我的脚本 - 这不是很好,所以我希望有人能想出更好的方法。
回答by Terry Jan Reedy
Autorepeat behavior is system dependent. In Win7,
自动重复行为取决于系统。在Win7中,
down a
down a
down a
...
down a
up a
This is for less than a second.
这是不到一秒钟。
回答by Terry Jan Reedy
how about;
怎么样;
from Tkinter import *
wn = Tk()
wn.title('KeyDetect')
m = 0
def down(e):
if m == 0:
print 'Down\n', e.char, '\n', e
global m
m = 1
def up(e):
if m == 1:
print 'Up\n', e.char, '\n', e
global m
m = 0
wn.bind('<KeyPress>', down)
wn.bind('<KeyRelease>', up)
wn.mainloop()
now it won't repeat.
现在它不会重复了。
回答by Artur Hawkwing
Well, this is a bit late now, but I have a solution that works. It's not great, but it does not require os.system overwriting system settings, which is nice.
好吧,现在有点晚了,但我有一个有效的解决方案。这不是很好,但它不需要 os.system 覆盖系统设置,这很好。
Basically, I make a class that records the timing of key presses. I say that a key is down when it has been pressed in the last short amount of time (here, .1ms). To get a press, it is easy enough: if the key is not registered as pressed, trigger the event. For releases, the logic is harder: if there is a suspected release event, set a timer for a short time (here, .1s) and then check to make sure the key is not down.
基本上,我制作了一个记录按键时间的类。我说一个键在最后很短的时间内被按下时(这里是 0.1 毫秒)。要获得按下,很容易:如果键未注册为按下,则触发事件。对于释放,逻辑更难:如果有一个可疑的释放事件,设置一个很短的时间(这里是 0.1 秒)的计时器,然后检查以确保键没有按下。
Once you have validated a press or release, call the on_key_press or on_key_release methods in your code. As for those, just implement them the way you originally wanted them
验证新闻或发布后,请在代码中调用 on_key_press 或 on_key_release 方法。至于那些,只需按照您最初想要的方式实现它们
I know this is not perfect, but I hope it helps!!
我知道这并不完美,但我希望它有所帮助!!
Here is the code:
这是代码:
Where you are initializing keypress events:
您在哪里初始化按键事件:
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')
Here is my custom KeyTracker class:
这是我的自定义 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()