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_())