Python 在TKinter中执行函数期间拒绝事件
我有一个TKinter应用程序(Python),它对按钮按下和键盘输入做出反应。但是,在这些事件之一之后调用的函数可能需要一些时间才能执行。我希望GUI在函数执行时拒绝所有用户输入。[编辑:只想澄清:所有用户输入指应用程序中存在的任何和所有按钮/键绑定-我不只是试图拒绝特定按钮的事件。] 下面是一个非常简单的示例,说明TKinter当前似乎将事件添加到处理每个事件后执行的队列中。每次按下按钮时,按钮中的文本都会附加一个零。但是,如果在文本读取Python 在TKinter中执行函数期间拒绝事件,python,tkinter,Python,Tkinter,我有一个TKinter应用程序(Python),它对按钮按下和键盘输入做出反应。但是,在这些事件之一之后调用的函数可能需要一些时间才能执行。我希望GUI在函数执行时拒绝所有用户输入。[编辑:只想澄清:所有用户输入指应用程序中存在的任何和所有按钮/键绑定-我不只是试图拒绝特定按钮的事件。] 下面是一个非常简单的示例,说明TKinter当前似乎将事件添加到处理每个事件后执行的队列中。每次按下按钮时,按钮中的文本都会附加一个零。但是,如果在文本读取00时按下按钮,则函数需要一段时间才能执行(我在(30
00
时按下按钮,则函数需要一段时间才能执行(我在(3000)之后输入了一个self.after),如果在该函数执行时按下按钮,则每次按下都会被注册。因此,如果我在“暂停”的3秒内按下按钮5次,那么每次点击都会注册,最后我会看到按钮上出现0000000
import tkinter as tk
# To demonstrate that keystrokes/button clicks do register while a function is executing (and then subsequently fire)
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
# Build the app
self.text = tk.StringVar()
self.pack()
self.create_widgets()
def create_widgets(self):
self.btn = tk.Button(self, textvariable=self.text, command=self.DoSomething, padx=30, pady=30)
self.btn.grid(row=0, column=0)
self.text.set('0')
def DoSomething(self):
# self.RejectEventsWhileThisFuncExecutes()
old_msg = self.text.get()
if old_msg == '00':
self.after(3000)
self.text.set(old_msg + '0')
# self.BeginAcceptingEventsAgain()
root = tk.Tk()
app = Application(master=root)
app.mainloop()
基本上,我想要的是我可以在函数的开头和结尾调用
DoSomething()
,比如说self.rejectEvents当函数执行时()
和self.beginAcceptingEventsGain()
,这将确保在函数执行时不会记录任何单击。您可以从DoSomething
开头的按钮中删除命令:
self.btn.config(command=lambda: None)
然后在最后重置它。只需确保在重新绑定之前update
处理所有排队事件:
self.update()
self.btn.config(command=self.DoSomething)
一种常见的策略是创建一个不可见的小部件(例如:窗口角落的1x1帧),并在该小部件上执行抓取(即:call
grab\u set
)。这将导致所有事件都被导入到该小部件。只要该窗口上没有绑定,净效果就是忽略事件。在删除抓取之前,您只需刷新事件队列(调用update
方法)。尽管这在如此简单的情况下确实有效,但如果有多个按钮和多个键绑定,这似乎很乏味。我想拒绝所有用户输入,而不仅仅是那个特定的按钮。为什么不在函数调用开始时禁用所有按钮,然后将它们恢复到正常状态?顺便说一句,一般来说,为本应是后台任务的东西“冻结”UI是不好的。我建议改为多线程。用户往往不耐烦。