PyQt5执行耗时操作导致界面卡死的解决办法

场景:当用PyQt5开发一个工具 ,需要查询数据库时,一旦查询数据量大,界面就容易出现卡死、未响应等问题。

原因:推测原因: 在PyQt中,GUI界面本身就是一个主线程,当进行耗时查询时,查询操作直接跑在这个主线程上,GUI需要等待查询操作完成后才会响应,在等待这段时间,整个GUI就处于卡死的状态。在windows下,系统会认为这个程序运行出错了,会自动显示未响应,进而关闭程序。

解决办法:另开一个线程来执行这个查询操作(使用QThread)

例子如下(由于代码不方便展示,采用别人的例子):

# coding=utf-8
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QLabel, QHBoxLayout, QPushButton)
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt, QThread, pyqtSignal


class MyGui(QWidget):
    """基础Gui页面"""

    def __init__(self):
        super().__init__()
        self.init_ui()  # 主窗口

    def init_ui(self):
        # self.setGeometry(300, 300, 600, 200)  # 设置主窗口的位置和大小
        self.setWindowTitle('Simple Little tools')  # 设置主窗口的标题
        self.setWindowIcon(QIcon('pics/icon1.gif'))  # 设置主窗口的图标(左上角)

        # 通用样式。页面上创建的一些部件,会默认使用设置的通用样式
        self.setStyleSheet(
            'QPushButton{font-weight: bold; background: skyblue; border-radius: 14px;'
            ' 300px; height: 28px; font-size: 20px; text-align: center;}'
            'QPushButton:hover{background: rgb(50, 150, 255);}'
            'QLabel{font-weight: bold; font-size: 20px; color: orange}'
        )
        self.main_layout()  # 布局函数
        self.show()  # 显示窗口

    def main_layout(self):
        self.btn = QPushButton(' 点击计算1+2+...+50000000 ')
        self.show_label = QLabel('                    ')
        self.show_label.setStyleSheet('color: black; background: skyblue; border-radius: 13px;')
        hbox = QHBoxLayout()
        hbox.addWidget(self.btn)
        hbox.addWidget(self.show_label)
        hbox.addStretch()
        self.setLayout(hbox)
        self.btn.clicked.connect(self.update)  # 按钮点击后创建一个新的线程

    def update(self):
        self.btn.setText('         计算中...        ')  # 主页面按钮点击后更新按钮文本
        self.btn.setEnabled(False)  # 将按钮设置为不可点击
        self.cal = CalSumTheard()  # 创建一个线程
        self.cal._sum.connect(self.update_sum)  # 线程发过来的信号挂接到槽函数update_sum
        self.cal.start()  # 线程启动

    def update_sum(self, r):
        self.show_label.setText('  ' + r + '  ')  # 信号发过来时,更新QLabel内容
        self.btn.setText(' 点击计算1+2+...+50000000 ')  # 更新按钮
        self.btn.setEnabled(True)  # 让按钮恢复可点击状态


class CalSumTheard(QThread):
    """该线程用于计算耗时的累加操作"""
    _sum = pyqtSignal(str)  # 信号类型 str

    def __init__(self):
        super().__init__()

    def run(self):
        s, k = 0, 0
        while k <= 50000000:
            s += k
            k += 1
        self._sum.emit(str(s))  # 计算结果完成后,发送结果


if __name__ == '__main__':
    app = QApplication(sys.argv)
    qt = MyGui()
    sys.exit(app.exec_())

  

posted @ 2022-08-26 15:57  Frank13054  阅读(3769)  评论(0编辑  收藏  举报