在外部循环中更新 Tkinter GUI
Posted
技术标签:
【中文标题】在外部循环中更新 Tkinter GUI【英文标题】:Update Tkinter GUI while in outside loop 【发布时间】:2019-04-16 21:15:44 【问题描述】:我的代码设置为打印出来以控制它的进度,因为它循环了几千个项目。这工作得非常好,直到我将它打包并分发给其他人,因为不再有控制台。我当前的方法有效,但在循环继续运行时,GUI 在几次迭代后始终挂起。
下面的示例代码运行,但我的循环要复杂得多并且挂断了。我很好奇是否有更好的方法来实现这一点,因为我喜欢使用这些 GUI,但是当我处于不同的循环中时,我还没有找到一种将数据发送到 GUI 的好方法。
from tkinter import *
import time
def do_loop(num_cycles):
for i in range(0, int(num_cycles)):
time.sleep(.25)
# print(i)
GUI_MSG.set(str(i))
Tk.update_idletasks(FORM)
FORM = Tk()
GUI_MSG = StringVar()
FORM.wm_title('Perform Element Analysis')
IO_FRAME = LabelFrame(FORM, text=' Input/Output Directories ')
IO_FRAME.grid(row=0, sticky='W', padx=5, pady=5, ipadx=5, ipady=5)
Label(IO_FRAME, text="Numer of Loops").grid(
row=1, column=1, padx=5, pady=(10, 2), sticky='E')
NUMBER_LOOPS = Entry(IO_FRAME, width=10)
NUMBER_LOOPS.grid(row=1, column=2, columnspan=4)
Button(FORM, text='Generate Tables', command=lambda: do_loop(
NUMBER_LOOPS.get())).grid(row=3, column=0, sticky='WE', padx=5, pady=5)
Label(FORM, textvariable=GUI_MSG).grid(row=2, sticky='WE', padx=5, pady=20)
FORM.mainloop()
【问题讨论】:
【参考方案1】:time.sleep()
Sleep 会冻结 tkinter GUI,因此您无法在 GUI 运行时执行任何其他操作。如python文档中所述(https://docs.python.org/3/library/time.html#time.sleep)
在给定的秒数内暂停执行调用线程
考虑到您想要使用的输出,您会得到更好的服务
.after()
而且您可能真的不需要 update_idletasks()。看看这是否适合你:
from tkinter import *
class myFormWindow():
def __init__(self,FORM):
self.count=0
self.GUI_MSG = StringVar()
self.FORM=FORM
self.FORM.wm_title('Perform Element Analysis')
IO_FRAME = LabelFrame(self.FORM, text=' Input/Output Directories ')
IO_FRAME.grid(row=0, sticky='W', padx=5, pady=5, ipadx=5, ipady=5)
Label(IO_FRAME, text="Numer of Loops").grid(
row=1, column=1, padx=5, pady=(10, 2), sticky='E')
self.NUMBER_LOOPS = Entry(IO_FRAME, width=10)
self.NUMBER_LOOPS.grid(row=1, column=2, columnspan=4)
Button(self.FORM, text='Generate Tables', command=self.get_cycles).grid(row=3, column=0, sticky='WE', padx=5, pady=5)
Label(self.FORM, textvariable=self.GUI_MSG).grid(row=2, sticky='WE', padx=5, pady=20)
def get_cycles(self):
self.num_cycles=self.NUMBER_LOOPS.get()
self.do_loop()
def do_loop(self):
if self.count<int(self.num_cycles):
self.GUI_MSG.set(str(self.count))
self.count+=1
self.FORM.after(1000,self.do_loop)
if __name__=="__main__":
FORM=Tk()
form_window=myFormWindow(FORM)
FORM.mainloop()
【讨论】:
这行得通,但理想情况下,循环将在课堂之外工作。正如我所说,我有相当广泛的函数集,这些函数没有意义包含在 GUI 类中。睡眠也仅用于示例。具体来说,我的代码所做的是它使用 GUI 让用户选择一组数据作为输入,它使用这些输入来创建断裂分析输入文件,然后使用 os.system(frac_analysis.exe.after()
可用于调用类外的函数。您将需要重新排列代码以适合您所需的行为。这个 NMT 文档 after doc 可能会有所帮助。【参考方案2】:
按照您问题的初始逻辑并使用.after()
在函数外部进行引用:
from tkinter import *
def do_loop():
global count,num_cycles,GUI_MSG
if count<int(num_cycles):
GUI_MSG.set(str(count))
count+=1
FORM.after(1000,do_loop)
def get_cycles():
global num_cycles
num_cycles=NUMBER_LOOPS.get()
do_loop()
count=0
FORM = Tk()
GUI_MSG = StringVar()
FORM.wm_title('Perform Element Analysis')
IO_FRAME = LabelFrame(FORM, text=' Input/Output Directories ')
IO_FRAME.grid(row=0, sticky='W', padx=5, pady=5, ipadx=5, ipady=5)
Label(IO_FRAME, text="Numer of Loops").grid(
row=1, column=1, padx=5, pady=(10, 2), sticky='E')
NUMBER_LOOPS = Entry(IO_FRAME, width=10)
NUMBER_LOOPS.grid(row=1, column=2, columnspan=4)
Button(FORM, text='Generate Tables', command=get_cycles).grid(row=3, column=0, sticky='WE', padx=5, pady=5)
Label(FORM, textvariable=GUI_MSG).grid(row=2, sticky='WE', padx=5, pady=20)
FORM.mainloop()
【讨论】:
以上是关于在外部循环中更新 Tkinter GUI的主要内容,如果未能解决你的问题,请参考以下文章