我在用tkinter做一个进度窗口
用重定向将项目子模块程序内的打印输出到进度窗口的text控件内
目前存在的问题是:
进度窗口有进度条,但进度条卡顿,必须等到text控件内有输出内容后,窗口才能刷新,进度条才能动一下。
这个问题是因为Tkinter的GUI更新是单线程的,也就是说在执行打印输出时,GUI会被阻塞,直到输出完成才会进行刷新。因此,您需要将进度更新与打印输出分离,以避免GUI被阻塞。以下是一个可能的解决方案:
Text
控件和一个Scrollbar
控件,用于显示和滚动文本。Text
控件中。下面是一个简单的示例代码:
import threading
import queue
import time
import tkinter as tk
class ProgressWindow(threading.Thread):
def __init__(self):
super().__init__()
self.queue = queue.Queue()
self.progress = 0
self.root = tk.Tk()
self.text = tk.Text(self.root)
self.text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.scrollbar = tk.Scrollbar(self.root)
self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.text.config(yscrollcommand=self.scrollbar.set)
self.scrollbar.config(command=self.text.yview)
self.progressbar = tk.Canvas(self.root, width=200, height=20, bg='white')
self.progressbar.pack(side=tk.BOTTOM, padx=5, pady=5)
self.start()
def run(self):
while self.progress < 100:
self.progressbar.delete("all")
self.progressbar.create_rectangle(0, 0, self.progress * 2, 20, fill="green")
self.root.update()
time.sleep(0.1)
def append_text(self, text):
self.queue.put(text)
def update_progress(self, progress):
self.progress = progress
def show(self):
self.root.mainloop()
class RedirectText:
def __init__(self, text_ctrl):
self.output = text_ctrl
def write(self, string):
self.output.append_text(string)
def run_submodule():
for i in range(10):
print("Output from submodule: {}".format(i))
time.sleep(1)
if __name__ == "__main__":
window = ProgressWindow()
sys.stdout = RedirectText(window.text)
window.show()
t = threading.Thread(target=run_submodule)
t.start()
for i in range(10):
window.update_progress((i + 1) * 10)
time.sleep(1)
t.join()
window.update_progress(100)
在这个示例代码中,我们创建了一个ProgressWindow
类来表示进度窗口。该类继承自threading.Thread
类,并在构造函数中创建了一个Text
控件和一个Scrollbar
控件,以及一个进度条的Canvas
控件。在run()
方法中,我们循环更新进度条的进度,并使用self.root.update()
方法实时刷新GUI。