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

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# 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 @   Frank13054  阅读(3939)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示