问题
每次运行到耗时方法时界面就卡死,无响应,花费了很长事件才把问题解决了,记录一下
原因分析
程序在主线程中执行,当主程序中有一个事件比较耗时时,主程序就会等耗时事件处理完才会进行下一步,此时界面就会卡死出现无响应的状态
解决办法
- 使用多线程
主线程只执行界面显示
子线程中执行耗时任务
简单Qthread实现
当使用PyQt编写GUI应用程序时,可以使用QThread类来执行耗时的任务,以避免主线程阻塞和页面无响应的问题。下面是一个简单的完整可运行代码示例,演示了如何在PyQt中使用QThread。
import sys
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton# 自定义的工作线程类
class WorkerThread(QThread):# 定义一个信号,用于在工作完成后发送通知finished = pyqtSignal()def run(self):# 执行耗时的任务self.do_work()# 发送工作完成的信号self.finished.emit()def do_work(self):# 模拟耗时的任务import timetime.sleep(5)# 主窗口类
class MainWindow(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("QThread示例")self.setGeometry(100, 100, 300, 200)self.label = QLabel("等待工作完成...", self)self.label.setGeometry(50, 50, 200, 30)self.start_button = QPushButton("开始", self)self.start_button.setGeometry(100, 100, 100, 30)self.start_button.clicked.connect(self.start_work)self.worker_thread = WorkerThread()self.worker_thread.finished.connect(self.on_worker_finished)def start_work(self):# 启动工作线程self.worker_thread.start()def on_worker_finished(self):# 工作完成后更新标签文字self.label.setText("工作完成!")if __name__ == "__main__":app = QApplication(sys.argv)window = MainWindow()window.show()sys.exit(app.exec_())
在这个示例中,我们创建了一个自定义的工作线程类WorkerThread
,继承自QThread
。在WorkerThread
中,我们重写了run
方法,该方法会在线程启动时自动调用。在run
方法中,我们执行了一个模拟的耗时任务do_work
,在任务完成后发送了一个自定义的信号finished
。
在主窗口类MainWindow
中,我们创建了一个QLabel
控件用于显示文字。在窗口初始化时,我们创建了一个WorkerThread
实例,并将其finished
信号连接到槽函数on_worker_finished
。然后,我们调用start_work
方法启动工作线程。
当工作线程完成任务时,会发出finished
信号,触发槽函数on_worker_finished
。在槽函数中,我们更新了标签控件的文字,将其设置为"工作完成!"。(只有在工作线程发射finished
信号后,槽函数self.on_worker_finished
才会被调用。)
通过使用QThread
,耗时的任务在工作线程中执行,不会阻塞主线程,从而避免了页面无响应的问题。同时,通过使用信号和槽机制,我们可以在工作完成后更新UI控件的状态。
总结思路:
通过点击按钮触发启动工作线程,线程的run()方法完成耗时任务,完成后发送完成信号后便可触发控件显示文字。