当 "computation heavy" 函数是 运行 时,如何阻止 tkinter window 不可交互

how do i stop the tkinter window being not interactable while a "computation heavy" function is running

我有一个 tkinter window 确实有一些用户可以与之交互的小部件,当一个功能需要一点时间 运行 整个 window 不能互动with.and我想改变

我听说你可以通过对函数实现多处理来解决这个问题,但我不太明白如何实现它。

我的代码是这样的:

import tkinter as tk
from tkinter import *


def functionthattakessometime():

    while True:
         print("haa")

root=tk.Tk()

b=Button(root,text="print haha",command=functionthattakessometime)

a=Button(root,text="do nothing")

b.pack()

root.mainloop()

按下 "print haha" 按钮后无法按下 "do nothing" window,我想更改它 因此即使在按下 "print haha" 按钮后,您也可以按下 "do nothing" 按钮。

threading 库就是您想要的。

这是一个简单的示例,说明它如何与您的代码一起工作。

import tkinter as tk
import threading


root = tk.Tk()
allow_print = True


def function_that_takes_sometime():
    while allow_print:
        print("haha")


def start_thread():
    global allow_print
    allow_print = True
    thread = threading.Thread(target=function_that_takes_sometime)
    thread.start()


def stop_thread():
    global allow_print
    allow_print = False


tk.Button(root, text="print haha", command=start_thread).pack()
tk.Button(root, text="Stop print", command=stop_thread).pack()

root.mainloop()

也就是说我会改变一些东西。

首先,我会删除 from tkinter import *,因为你不应该两次导入 tkinter,最好只使用 import tkinter as tk,因为这可以防止我们意外覆盖任何方法。

其次,我会在 class 中构建它,这样我们就可以避免使用全局变量。

这是一个 OOP 版本:

import tkinter as tk
import threading


class Main(tk.Tk):
    def __init__(self):
        super().__init__()
        self.allow_print = True
        tk.Button(self, text="print haha", command=self.start_thread).pack()
        tk.Button(self, text="Stop print", command=self.stop_thread).pack()

    def function_that_takes_sometime(self):
        while self.allow_print:
            print("haha")

    def start_thread(self):
        self.allow_print = True
        thread = threading.Thread(target=self.function_that_takes_sometime)
        thread.start()

    def stop_thread(self):
        self.allow_print = False


Main().mainloop()

为了进一步简化这一点,因为线程通常是矫枉过正的,我们可以使用 after() 方法来管理循环而不影响主循环。

import tkinter as tk


class Main(tk.Tk):
    def __init__(self):
        super().__init__()
        self.allow_print = True
        tk.Button(self, text="print haha", command=self.function_that_takes_sometime).pack()
        tk.Button(self, text="Stop print", command=self.stop_print).pack()

    def function_that_takes_sometime(self):
        if self.allow_print:
            print("haha")
            self.after(1000, self.function_that_takes_sometime)

    def stop_print(self):
        self.allow_print = False


Main().mainloop()