当 "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()
我有一个 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()