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

时间:2018-10-04 14:39:48

标签: python tkinter

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

这是一个非常简单的示例,它表明TKinter当前似乎将事件添加到队列中,该队列在处理每个事件之后执行。每次按下按钮时,按钮中的文本都会附加一个零。但是,如果在文本显示为00时按下了按钮,则该函数需要一段时间才能执行(我放入了self.after(3000)),如果在执行该函数时按下了按钮,则这些印刷机中的每一个都会注册。因此,如果我在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.RejectEventsWhileThisFuncExecutes()self.BeginAcceptingEventsAgain(),这可以确保不会函数执行时会记录点击。

2 个答案:

答案 0 :(得分:1)

您可以从DoSomething开始的按钮中删除命令:

self.btn.config(command=lambda: None)

然后在最后将其重置。只需在重新绑定之前确保update处理所有排队的事件:

self.update()
self.btn.config(command=self.DoSomething)

答案 1 :(得分:1)

一种常见的策略是创建一个不可见的窗口小部件(例如:窗口角处的1x1帧),然后对该窗口小部件进行抓取(即:调用grab_set)。这导致所有事件都被漏斗到该小部件。只要该窗口上没有绑定,最终的结果就是事件将被忽略。您只需要先清除事件队列(调用update方法),然后再删除抓斗。