TkInter按键,键盘释放事件

los*_*ost 25 python tkinter

据我所知,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"重置它.问题是这是全局行为 - 不只是我的脚本 - 这不是很好,所以我希望有人能想出更好的方法.


Jef*_*lge 7

好吧,现在有点晚了,但我有一个可行的解决方案。这不是很好,但它不需要 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)

  • 哈,基本上是软件去抖!这是个好主意,尽管我们必须这样做似乎很疯狂 (7认同)

Ter*_*edy 5

自动重复行为取决于系统。在Win7中,

down a
down a
down a
...
down a
up a
Run Code Online (Sandbox Code Playgroud)

这是不到一秒钟。