防止 tkinter 中的事件队列
Prevent a queue of events in tkinter
我已经使用 TkInter 制作了一个 GUI。
现在我试图在按键后执行一个动作。
但是,我不希望在单击按钮两次时执行两次操作。
相反,程序应该等到上一个动作完成后才开始等待下一个按键。
我似乎无法实现这一点,即使是命令处理程序 returns "break"
。
请参阅下面的最小工作示例,如果您多次按下 <Left>
按钮,代码也会执行多次。我应该如何更改代码以达到所需的性能?
import tkinter as tk
import time
class App(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self)
# Create handler
def event_handler(event):
print('One run for event', event)
time.sleep(1)
print('Done')
return "break"
# Button
self.button = tk.Button(
master=self,
text='Test',
command = event_handler
)
self.button.grid()
self.bind('<Left>', event_handler)
self.focus()
if __name__ == "__main__":
root = tk.Tk()
root.title("TestTool")
# Start application
app = App(root)
app.pack(fill="both", expand=True)
root.mainloop()
当您使用 time.sleep(1)
执行您的 event_handler
时,您实际上是在阻止任何其他事件的执行。但是事件触发器是一个接一个地累积和执行的,每个event_handler
是如何开始和结束的。它创建 event_handler
.
串行执行的效果
你想要的是设置一些标志来指示你的事件状态。然后你必须处理你的 return
来自 event_handler
之前的所有累积事件。这将导致所有事件执行,但立即 return
,因为标志设置为 True
:event is 运行.
这是代码片段:
import time
import tkinter as tk
class App(tk.Frame):
event_running = False
def __init__(self, parent):
tk.Frame.__init__(self)
# Create handler
def event_handler(event=None):
# Check if event is running
if self.event_running:
return False
# Lock event until it's finished
self.event_running = True
print('One run for event', event)
time.sleep(1)
print('Done')
# Update all pending events
self.update()
self.update_idletasks()
# Release event handler
self.event_running = False
return
# Button
self.button = tk.Button(
master=self,
text='Test',
command=event_handler
)
self.button.grid()
self.bind('<Left>', event_handler)
self.focus()
if __name__ == "__main__":
root = tk.Tk()
root.title("TestTool")
# Start application
app = App(root)
app.pack(fill="both", expand=True)
root.mainloop()
我已经使用 TkInter 制作了一个 GUI。
现在我试图在按键后执行一个动作。
但是,我不希望在单击按钮两次时执行两次操作。
相反,程序应该等到上一个动作完成后才开始等待下一个按键。
我似乎无法实现这一点,即使是命令处理程序 returns "break"
。
请参阅下面的最小工作示例,如果您多次按下 <Left>
按钮,代码也会执行多次。我应该如何更改代码以达到所需的性能?
import tkinter as tk
import time
class App(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self)
# Create handler
def event_handler(event):
print('One run for event', event)
time.sleep(1)
print('Done')
return "break"
# Button
self.button = tk.Button(
master=self,
text='Test',
command = event_handler
)
self.button.grid()
self.bind('<Left>', event_handler)
self.focus()
if __name__ == "__main__":
root = tk.Tk()
root.title("TestTool")
# Start application
app = App(root)
app.pack(fill="both", expand=True)
root.mainloop()
当您使用 time.sleep(1)
执行您的 event_handler
时,您实际上是在阻止任何其他事件的执行。但是事件触发器是一个接一个地累积和执行的,每个event_handler
是如何开始和结束的。它创建 event_handler
.
你想要的是设置一些标志来指示你的事件状态。然后你必须处理你的 return
来自 event_handler
之前的所有累积事件。这将导致所有事件执行,但立即 return
,因为标志设置为 True
:event is 运行.
这是代码片段:
import time
import tkinter as tk
class App(tk.Frame):
event_running = False
def __init__(self, parent):
tk.Frame.__init__(self)
# Create handler
def event_handler(event=None):
# Check if event is running
if self.event_running:
return False
# Lock event until it's finished
self.event_running = True
print('One run for event', event)
time.sleep(1)
print('Done')
# Update all pending events
self.update()
self.update_idletasks()
# Release event handler
self.event_running = False
return
# Button
self.button = tk.Button(
master=self,
text='Test',
command=event_handler
)
self.button.grid()
self.bind('<Left>', event_handler)
self.focus()
if __name__ == "__main__":
root = tk.Tk()
root.title("TestTool")
# Start application
app = App(root)
app.pack(fill="both", expand=True)
root.mainloop()