QT GUI调用ProcessPoolExecutor生成TIF时冻结,如何添加进度条?
问题解决思路与代码修改
你的GUI冻结核心原因是asyncio.get_event_loop().run_until_complete()阻塞了QT的主线程事件循环,导致界面无法响应交互。同时当前代码没有实现任务进度的实时反馈机制,以下是针对性的解决方案:
1. 先定义QT信号用于跨进程更新GUI
在你的窗口类中添加进度更新信号,确保GUI操作始终在主线程执行(跨进程/线程不能直接操作QT控件):
from PyQt5.QtCore import pyqtSignal, pyqtSlot class YourMainWindow(...): # 定义进度更新信号,参数为进度百分比 progress_update = pyqtSignal(int) def __init__(self): super().__init__() # 将信号绑定到进度条显示函数 self.progress_update.connect(self.progress_display) self.completed_tasks = 0 self.total_tasks = 0
2. 修改按钮点击槽函数,异步执行任务并反馈进度
去掉asyncio相关代码,直接用ProcessPoolExecutor异步提交任务,通过回调函数更新进度:
@pyqtSlot() def on_pb_start_clicked(self): if self.anaglyph_output is None or self.tmp_output is None: self.display_no_path_warning() return # 初始化进度计数 self.completed_tasks = 0 df = self.mask_df self.total_tasks = 10 # 对应原代码的df_size,可根据实际任务数调整 workers = self.cpu_selected args = [(i, df[df.fid == i + 1.0], self.anaglyph_output, self.tmp_output) for i in range(self.total_tasks)] # 初始化进度条为0 self.progress_display(0) from concurrent.futures import ProcessPoolExecutor executor = ProcessPoolExecutor(max_workers=workers) def task_finished(future): # 任务完成后更新进度 self.completed_tasks += 1 current_progress = int((self.completed_tasks / self.total_tasks) * 100) # 通过信号触发主线程更新GUI self.progress_update.emit(current_progress) # 所有任务完成后关闭进程池 if self.completed_tasks == self.total_tasks: executor.shutdown() # 这里可以添加任务完成后的逻辑,比如弹出提示 # 批量提交任务并绑定回调 for arg in args: future = executor.submit(create_anaglyph, *arg) future.add_done_callback(task_finished)
关键注意事项
create_anaglyph必须是可被pickle序列化的函数(不能是类的非静态方法),否则进程池无法正常传递任务- 所有GUI更新操作必须通过QT信号触发,禁止在回调函数中直接修改控件
- 如果需要单个任务内部的实时进度(而非仅任务完成计数),可以用
multiprocessing.Queue在子进程中传递进度片段,主线程监听队列并更新进度条
内容的提问来源于stack exchange,提问作者Mily
相关产品推荐
相关产品推荐

