Python 在TKinter中执行函数期间拒绝事件

Python 在TKinter中执行函数期间拒绝事件,python,tkinter,Python,Tkinter,我有一个TKinter应用程序(Python),它对按钮按下和键盘输入做出反应。但是,在这些事件之一之后调用的函数可能需要一些时间才能执行。我希望GUI在函数执行时拒绝所有用户输入。[编辑:只想澄清:所有用户输入指应用程序中存在的任何和所有按钮/键绑定-我不只是试图拒绝特定按钮的事件。] 下面是一个非常简单的示例,说明TKinter当前似乎将事件添加到处理每个事件后执行的队列中。每次按下按钮时,按钮中的文本都会附加一个零。但是,如果在文本读取00时按下按钮,则函数需要一段时间才能执行(我在(30

我有一个TKinter应用程序(Python),它对按钮按下和键盘输入做出反应。但是,在这些事件之一之后调用的函数可能需要一些时间才能执行。我希望GUI在函数执行时拒绝所有用户输入。[编辑:只想澄清:所有用户输入指应用程序中存在的任何和所有按钮/键绑定-我不只是试图拒绝特定按钮的事件。]

下面是一个非常简单的示例,说明TKinter当前似乎将事件添加到处理每个事件后执行的队列中。每次按下按钮时,按钮中的文本都会附加一个零。但是,如果在文本读取
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是不好的。我建议改为多线程。用户往往不耐烦。