我的应用程序偶尔会运行一些耗时的后台进程。我想表明应用程序正在使用简单的不确定 ttk.Progressbar
。
但是,我的实现只显示静态进度条。
无论如何,这是我实施它的方式。
class MyApp(ttk.Frame):
def __init__(self, master):
ttk.Frame.__init__(self, master)
fname = 'test.txt'
self.build_ui()
self.process_file(fname)
def process_file(self, fname):
self.show_progress(True)
fdata = self.read_file(fname)
fdata = self.spellcheck(fdata)
self.show_progress(False)
return fdata
def show_progress(self, start)
if start:
self.prog_win = tk.Toplevel()
self.prog_win.title('Working...')
self.prog_win.resizable(0, 0)
self.progress_bar = ttk.Progressbar(self.prog_win,
orient=tk.HORIZONTAL,
mode='indeterminate',
takefocus=True)
self.progress_bar.grid()
self.progress_bar.start()
else:
self.progress_bar.stop()
self.prog_win.destroy()
root = tk.Tk()
root.update()
gui = MyApp(root)
gui.mainloop()
上述代码无法正常运行。 Progressbar
显示为静态,它不会移动,只会永远挂在那里。我尝试使用线程但是如果我在单独的show_progress
中启动Thread
,它总是在处理完成后执行。
我做错了什么?
答案 0 :(得分:2)
问题是self.read_file()
和self.spellcheck()
阻塞,阻止Tkinter在其主循环中更新进度条。解决此问题的一种简单方法是在单独的线程中进行处理,并定期检查线程是否完成了它的工作。
import threading
class MyApp(ttk.Frame):
def __init__(self, master):
ttk.Frame.__init__(self, master)
fname = 'test.txt'
self.build_ui()
self.process_file(fname)
def process_file(self, fname):
self.show_progress(True)
# Start thread to process file.
self.thread = threading.Thread(target=self.process_file_worker, args=(fname,))
self.thread.daemon = True # Allow the program to terminate without waiting for the thread to finish.
self.thread.start()
# Start checking the thread.
self.process_file_check()
def process_file_check(self):
if self.thread.is_alive():
# Thread is still running, check thread again in 10 milliseconds.
self.after(10, self.process_file_check)
else:
# Thread finished, handle processed results.
# Do something with `self.fdata`.
self.show_progress(False)
def process_file_worker(self, fname):
# This is run inside the thread.
fdata = self.read_file(fname)
fdata = self.spellcheck(fdata)
self.fdata = fdata
def show_progress(self, start):
if start:
self.prog_win = tk.Toplevel()
self.prog_win.title('Working...')
self.prog_win.resizable(0, 0)
self.progress_bar = ttk.Progressbar(self.prog_win,
orient=tk.HORIZONTAL,
mode='indeterminate',
takefocus=True)
self.progress_bar.grid()
self.progress_bar.start()
else:
self.progress_bar.stop()
self.prog_win.destroy()
root = tk.Tk()
root.update()
gui = MyApp(root)
gui.mainloop()