如何实现带可终止线程的CustomTkinter进度条?
修正后的可终止线程+CTk进度条实现
你的代码存在几个关键问题导致功能失效,以下是修复后的完整实现,可实现进度条运行5秒后被中断的效果:
import customtkinter as ctk import threading import time class StoppableThread(threading.Thread): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._stop_event = threading.Event() def stop(self): self._stop_event.set() def stopped(self): return self._stop_event.is_set() class App(ctk.CTk): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.geometry("200x100") # 创建进度条 self.progress_bar = ctk.CTkProgressBar(master=self, height=15, width=150, mode='determinate') self.progress_bar.place(x=10, y=10) self.progress_bar.set(0) # 启动线程 self.alg_thread = Algorithm(self) self.alg_thread.start() # 5秒后触发停止操作(非阻塞) self.after(5000, self.stop_thread) def stop_thread(self): self.alg_thread.stop() print("线程已终止") class Algorithm(StoppableThread): def __init__(self, app, *args, **kwargs): super().__init__(*args, **kwargs) self.app = app # 保存App实例,用于安全更新UI def run(self): n = 100 # 增加迭代次数,让进度条动画更明显 iter_step = 1 / n progress = 0 while not self.stopped(): if progress >= 1: progress = 0 # 进度满了重置,方便演示 # 主线程安全更新进度条 self.app.after(0, lambda p=progress: self.app.progress_bar.set(p)) progress += iter_step time.sleep(0.05) # 模拟任务耗时 # 线程终止后重置进度条 self.app.after(0, lambda: self.app.progress_bar.set(0)) if __name__ == "__main__": app = App() app.mainloop()
关键改动说明:
- 线程执行逻辑:
Algorithm类重写了run()方法,线程启动后自动执行任务循环,替代原代码中未被调用的test()方法 - UI线程安全:所有进度条更新操作通过
app.after(0, ...)提交到主线程执行,避免子线程直接操作UI组件导致的线程安全问题 - 非阻塞延迟:用
self.after(5000, ...)替代time.sleep(5),不会阻塞主线程,保证UI始终响应 - 实例引用传递:将
App实例传入Algorithm线程,让线程能安全访问并更新UI组件 - 停止信号检查:在任务循环中持续检查
stopped()状态,收到停止信号后立即终止循环,并重置进度条
内容的提问来源于stack exchange,提问作者Andrew Eaves
相关产品推荐
相关产品推荐

