我有一个使用tkinter和键绑定的python程序。该程序调用外部程序,然后询问,如何处理它,期望n键为" no"或者是"是"的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()
在上面的代码片段中,我用sleep()替换了外部程序,并用空格键替换了键。如果在睡眠期间启动了python3 skript并且按下了两次空间,我会看到终端中的输出如下:
Step 1
Step 2
Step 1
Step 2
我想忽略在睡眠例程中引发的任何关键事件。接下来我尝试使用信号量,但这也没有成功。问题可能更复杂,因为如果我在睡眠期间按空格三次,我将得到以下结果:
Step 1
Step 2
Step 1
Step 1
Step 2
Step 2
看起来好像并行多次调用函数keypressed。是否有可能在接受新事件之前清除事件队列?
答案 0 :(得分:3)
这需要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()
答案 1 :(得分:1)
可能time.sleep方法正在搞乱Tkinter主循环。 您应该使用&#39;之后&#39;来自Tkinter模块的方法。
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/universal.html
如果你没有传递一个回调参数,这个方法会等待delay_ms毫秒,就像在标准Python时间模块的.sleep()函数中一样。
查看此帖子的示例: