Dir*_*rkS 4 python tkinter key-bindings keyboard-events
我有一个使用 tkinter 和键绑定的 python 程序。该程序调用外部程序,然后询问如何处理它,期望 n 键表示“否”,或 y 键表示“是”。问题:如果我按允许的键两次,第二个键将被存储并稍后处理 - 因此是错误的问题。
import tkinter as tk
import time
class App:
counter = 0
def __init__(self, master): # Constructor
# build GUI
self.label = tk.Label(text="Press <space>", width=40)
self.label.grid(row=1, column=1, sticky='w')
# bind keys to buttons
master.bind('<Key-space>', self.keyPressed)
pass # __init__
def keyPressed(self, event):
print("Step 1")
self.counter = self.counter + 1
self.label.configure(text = str(self.counter))
self.label.update()
time.sleep(3)
print("Step 2")
pass # Key1Pressed
# End of class App
root = tk.Tk()
root.option_add('*font', ('Arial', 11, 'bold'))
# root.attributes("-toolwindow", 1)
posX = root.winfo_screenwidth() - 500
posY = 30
root.geometry("+%d+%d" % (posX, posY))
root.title("Bind tester")
display = App(root)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)
在上面的代码片段中,我用 sleep() 和空格键的键绑定替换了外部程序。如果启动 python3 skript 并在睡眠期间按两次空格,我会在终端中看到如下输出:
Step 1
Step 2
Step 1
Step 2
Run Code Online (Sandbox Code Playgroud)
我想忽略在睡眠过程中引发的任何关键事件。所以接下来我尝试使用信号量,但这也没有成功。问题可能更复杂,因为如果我在睡眠期间按空格键三次,我将得到以下结果:
Step 1
Step 2
Step 1
Step 1
Step 2
Step 2
Run Code Online (Sandbox Code Playgroud)
看起来好像按键的功能被并行调用了多次。在接受新事件之前是否可以清除事件队列?
小智 5
这需要 Tkinter 鲜为人知的怪癖之一,即您必须从函数返回“break”。下面的程序将键重新绑定到返回“break”的“ignore()”函数。我不明白这是如何或为什么的,它被记录在http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm并且确实有效。
import sys
if sys.version_info[0] < 3:
import Tkinter as tk ## Python 2.x
else:
import tkinter as tk ## Python 3.x
class App:
def __init__(self, master): # Constructor
self.master=master
self.counter=0
# build GUI
self.label = tk.Label(text="Press <space>", width=40)
self.label.grid(row=1, column=1, sticky='w')
# bind keys to buttons
master.bind('<Key-space>', self.keyPressed)
def ignore(self, event):
print "ignore"
return "break"
def keyPressed(self, event):
self.master.bind('<Key-space>', self.ignore)
print("Step 1")
self.counter = self.counter + 1
self.label["text"] = str(self.counter)
self.master.after(3000, self.bindit)
print("Step 2")
def bindit(self):
self.master.bind('<Key-space>', self.keyPressed)
print("Step 3 = ready for more input")
root = tk.Tk()
root.option_add('*font', ('Arial', 11, 'bold'))
# root.attributes("-toolwindow", 1)
posX = root.winfo_screenwidth() - 500
posY = 30
root.geometry("+%d+%d" % (posX, posY))
root.title("Bind tester")
display = App(root)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)