在PyQt中,如果在UI线程里直接执行耗时操作,会导致界面无法正常更新信息、假死、无响应

例如,每隔一秒就输出时间到界面上,不使用线程的代码(简化后):

2023-11-21 09 58 57.png

运行结果如下:

Animation.webp

使用PyQt自带的线程Qthread,效果如下

Animation2.webp

主要思路:
创建一个继承Qthread的线程类,在类内设置自定义信号pyqtSignal,通过emit传递信号,最后交由UI去显示

主要代码如下:

import datetime
import sys
import time

from PyQt5 import QtCore
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtWidgets import QApplication,QFrame
from main.data_factory.data_creator2 import Ui_Frame


class thread_test(QFrame, Ui_Frame):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.create_btn.clicked.connect(self.create_fun)

    def create_fun(self):
        # 创建线程
        self.thread = Runthread(self)
        # 传递参数,没需求则不传
        # self.thread.accept()
        # 开始线程
        self.thread.begin()
        # 连接信号槽
        self.thread.signal1.connect(self.display)

    def display(self,msg:str):
        # 显示到UI界面
        self.result_area.setPlainText(msg)


# 线程类
class Runthread(QtCore.QThread):
    #  通过类成员对象定义信号对象
    signal1 = pyqtSignal(str)

    def __init__(self, parent=None):
        super(Runthread, self).__init__()

    def accept(self):
        # 自定义方法,可接受参数供线程处理,没需求则不用实现
        pass

    def run(self):
        while 1:
            self.signal1.emit(datetime.datetime.now().strftime("%H:%M:%S"))
            time.sleep(1)

    def begin(self):
        self.start()


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