在外部循环中更新Tkinter GUI

时间:2018-11-13 23:51:51

标签: python python-3.x tkinter

我设置了我的代码以打印出来,以控制进度,因为它遍历了数千个项目。直到我将其打包并分发给其他人(因为不再有控制台),这才能很好地工作。我当前的方法可行,但是在循环继续运行的同时,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()

2 个答案:

答案 0 :(得分:0)

time.sleep()

Sleep将冻结tkinter GUI,以使您无法在GUI运行时对其执行任何其他操作。如python doc(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()

答案 1 :(得分:0)

遵循问题的初始逻辑,并使用.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()