You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现PyQt5耗时代码执行期间持续显示等待窗口?

解决PyQt5中耗时任务运行时显示等待窗口的问题

嘿,我懂你想要实现的效果——在耗时代码执行完成前,让一个等待窗口一直显示,而且不能让UI假死对吧?直接在主线程里跑耗时函数(哪怕是替换掉time.sleep(2))都会卡住Qt的事件循环,导致等待窗口要么不显示,要么显示了也没法正常更新。咱们用QThread把耗时任务放到子线程里就能完美解决这个问题,下面是完整的实现方案:

核心思路

  • 把耗时任务从主线程剥离到独立的子线程中,避免阻塞UI事件循环
  • 用Qt的信号与槽机制,让子线程在任务完成时通知主线程关闭等待窗口
  • 等待窗口在主线程中显示,因为UI操作必须在主线程执行

完整代码示例

from PyQt5.QtWidgets import (QPushButton, QApplication, QMainWindow, 
                             QDialog, QVBoxLayout, QLabel)
from PyQt5.QtCore import QThread, pyqtSignal
import sys
import time

# 定义耗时任务的线程类
class WorkerThread(QThread):
    # 定义任务完成的信号
    task_finished = pyqtSignal()

    def run(self):
        # 这里替换成你的实际耗时函数
        print("开始执行耗时任务...")
        time.sleep(5)  # 模拟耗时操作,替换成你的业务代码
        print("耗时任务执行完成!")
        # 发送任务完成信号
        self.task_finished.emit()

# 等待窗口类
class MyWarnings(QDialog):
    '''Generic popup window with text.'''
    def __init__(self):
        super(MyWarnings, self).__init__()
        self.setWindowTitle("请稍候")
        self.setFixedSize(200, 100)
        widget = QLabel('正在处理,请等待...')
        layout = QVBoxLayout()
        layout.addWidget(widget)
        self.setLayout(layout)

# 主窗口类
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("主窗口")
        self.setFixedSize(300, 200)
        self.btn = QPushButton('启动耗时任务', self)
        self.btn.clicked.connect(self.start_long_task)
        self.btn.move(100, 80)

    def start_long_task(self):
        # 创建并显示等待窗口
        self.wait_dialog = MyWarnings()
        self.wait_dialog.show()

        # 创建工作线程
        self.worker = WorkerThread()
        # 连接线程完成信号到关闭等待窗口的槽函数
        self.worker.task_finished.connect(self.wait_dialog.close)
        # 连接线程完成信号到线程自身的删除(避免内存泄漏)
        self.worker.task_finished.connect(self.worker.deleteLater)
        # 启动线程
        self.worker.start()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

关键细节说明

  • WorkerThread类:专门用来执行耗时任务,run()方法里就是你的业务代码,任务完成时通过task_finished信号通知主线程
  • 等待窗口MyWarnings:简单的提示窗口,在主线程中显示,不会被阻塞
  • 信号与槽的连接:线程完成时自动关闭等待窗口,同时清理线程对象避免内存泄漏
  • 为什么不用time.sleep在主线程:因为Qt的UI事件循环在主线程,一旦主线程被耗时任务占用,就没法处理窗口的绘制、用户交互等事件,导致窗口假死

这样修改后,等待窗口会正常显示直到耗时任务完成,而且整个UI不会卡顿~

内容的提问来源于stack exchange,提问作者ignoring_gravity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:05:47