【问题标题】:Update Tkinter GUI while in outside loop在外部循环中更新 Tkinter GUI
【发布时间】: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()

【问题讨论】:

    标签: python python-3.x tkinter


    【解决方案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 )。 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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-26
      相关资源
      最近更新 更多