据我所知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()
按住&#34; a&#34;:
时的输出down a
up a
down a
up a
down a
up a
down a
up a
etc...
答案 0 :(得分:16)
好的更多研究发现this helpful post表明这是由于X的自动重复行为而发生的。您可以使用
禁用此功能os.system('xset r off')
然后使用脚本末尾的“on”重置它。 问题是这是全局行为 - 不仅仅是我的脚本 - 这不是很好,所以我希望有人能想出更好的方法。
答案 1 :(得分:3)
自动重复行为取决于系统。在Win7中,
down a
down a
down a
...
down a
up a
这不到一秒钟。
答案 2 :(得分:1)
怎么样;
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()
现在它不会重演。
答案 3 :(得分:1)
嗯,这有点迟了,但是我有一个可行的解决方案。这不是很好,但是它不需要os.system覆盖系统设置,这很好。
基本上,我制作了一个记录按键时间的类。我说是在最近的短时间内(这里是.1ms)按下了一个键。要获得按下,这很容易:如果按键未注册为按下,则触发事件。对于发行版,逻辑更难:如果存在可疑的发行事件,则将计时器设置为短时间(此处为.1s),然后检查以确保密钥没有按下。
验证了新闻稿或发布稿后,请在代码中调用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')
这是我自定义的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()
答案 4 :(得分:0)
诀窍是跟踪一个键有一个键按下的事实,哪些键当前被按下,以及不再有键按下的事实。一直无视键盘中继器。
这个小原型应该涵盖所有基础:
#Key press prototype
#Tracks keys as pressed, ignoring the keyboard repeater
#Current keys down are kept in a dictionary.
#That a key is pressed is flagged, and the last key pressed is tracked
import tkinter
winWid = 640
winHei = 480
keyDown = False
lastKey = "none"
keyChange = keyDown
keyList = {}
def onKeyDown(event):
global keyDown, lastKey, keyList
if (event.char in keyList) != True:
keyList[event.char] = "down"
print(keyList)
keyDown = True
lastKey = event.char
def onKeyUp(event):
global keyDown
if (event.char in keyList) == True:
keyList.pop(event.char)
if len(keyList) == 0:
keyDown = False
print(keyList)
#onTimer is present to show keyboard action as it happens.
#It is not needed to track the key changes, and it can be
#removed.
def onTimer():
global keyChange, timerhandle
if keyDown != keyChange:
keyChange = keyDown
if keyDown:
print("Key down, last key pressed - " + lastKey)
else:
print("Key up, last key pressed - " + lastKey)
timerhandle = window.after(20,onTimer)
def onShutdown():
window.after_cancel(timerhandle)
window.destroy()
window = tkinter.Tk()
frame = tkinter.Canvas(window, width=winWid, height=winHei, bg="black")
frame.pack()
frame.bind("<KeyPress>", onKeyDown)
frame.bind("<KeyRelease>", onKeyUp)
frame.focus_set()
timerhandle = window.after(20,onTimer)
window.protocol("WM_DELETE_WINDOW",onShutdown)
window.mainloop()