我有一个简单的GUI,它从另一个python文件运行各种脚本,一切正常,直到GUI运行一个包含while循环的函数,此时GUI似乎崩溃并变为非活动状态。有没有人对如何克服这个问题有任何想法,因为我认为这与更新的GUI有关,谢谢。下面是我的GUI的简化版本。
GUI
#!/usr/bin/env python
# Python 3
from tkinter import *
from tkinter import ttk
from Entry import ConstrainedEntry
import tkinter.messagebox
import functions
AlarmCode = "2222"
root = Tk()
root.title("Simple Interface")
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
ttk.Button(mainframe, width=12,text="ButtonTest",
command=lambda: functions.test()).grid(
column=5, row=5, sticky=SE)
for child in mainframe.winfo_children():
child.grid_configure(padx=5, pady=5)
root.mainloop()
功能
def test():
period = 0
while True:
if (period) <=100:
time.sleep(1)
period +=1
print(period)
else:
print("100 seconds has passed")
break
上面会发生的是,当循环运行时,应用程序将崩溃。如果我在句点结束后在else语句中插入一个break,一切都会正常工作。我希望用户能够在循环中单击,因为此GUI将运行许多不同的功能。
答案 0 :(得分:2)
不要在与Tkinter代码相同的线程中使用time.sleep
:它会冻结GUI,直到test
的执行完成。为避免这种情况,您应该使用after
窗口小部件方法:
# GUI
ttk.Button(mainframe, width=12,text="ButtonTest",
command=lambda: functions.test(root))
.grid(column=5, row=5, sticky=SE)
# functions
def test(root, period=0):
if period <= 100:
period += 1
print(period)
root.after(1000, lambda: test(root, period))
else:
print("100 seconds has passed")
<强>更新强>
在您的评论中,您还要添加您的代码不会使用time.sleep
,因此您的原始示例可能不是最合适的。在这种情况下,您可以创建一个新线程来运行密集型代码。
请注意,我首先发布了after
的替代方法,因为只有在完全必要时才应使用多线程 - 这会增加您的应用程序的开销,以及调试代码的更多困难。
from threading import Thread
ttk.Button(mainframe, width=12,text="ButtonTest",
command=lambda: Thread(target=functions.test).start())
.grid(column=5, row=5, sticky=SE)
# functions
def test():
for x in range(100):
time.sleep(1) # Simulate intense task (not real code!)
print(x)
print("100 seconds has passed")