PyQt界面阻塞卡死问题的解决
作者:机器人迈克猫
当用PyQt5开发一个GUI界面 ,需要执行业务逻辑时,后台逻辑执行时间长,界面就容易出现卡死、未响应等问题,本文主要介绍了PyQt界面阻塞卡死问题的解决
任何同学在使用类似PyQt(或者C#开发winform,WPF)开发带界面的软件的刚开始阶段,都会碰到界面卡死软件崩溃的问题。
就比如以下这段代码
import sys from PyQt5.Qt import * import time class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("更新界面案例") self.resize(300, 200) self.move(400, 250) def setup_ui(self): self.label = QLabel(self) self.label.setText("当前人数: 100") self.label.move(100, 50) self.btn1=QPushButton(self) self.btn1.setText("按钮1") self.btn1.move(50,125) self.btn1.clicked.connect(self.btn1_method) self.btn2=QPushButton(self) self.btn2.setText("按钮2") self.btn2.move(165,125) def btn1_method(self): # 以下为一通耗时操作,比如查询数据库 time.sleep(10) #根据上面逻辑操作的结果,更新界面 self.label.setText("当前人数: 200") if __name__ == "__main__": app = QApplication(sys.argv) window = Window() window.setup_ui() window.show() sys.exit(app.exec_())
运行之后,点击按钮1,会发现界面卡死了,有的人着急再点击几下界面,软件就直接芭比Q了。
造成这个现象的原因是,本来软件界面是一直占着主进程的,点击按钮之后,如果按钮执行的是长时间的操作,这个操作就把主进程占住不放了,没有进程来处理软件界面,这个时候界面就会卡死。
所以解决问题的思路就是主进程还是给软件界面,把按钮耗时的工作交给线程去处理,方法有很多,这里用PyQt中的QThread举例
class btn2Thread(QThread): def __init__(self): super(btn2Thread,self).__init__() def run(self): # 以下为一通逻辑操作,比如查询数据库 time.sleep(10) # 更新主界面,但是在QThread里找不到主界面的控件
但是这里又会出现一个问题,在执行完复杂操作去更新界面的时候,发现在QThread找不到主界面的控件,就不能更新主界面了。
解决方法是,在线程里找不到主界面的控件,在主界面的进程里我们是可以找到控件的,那我们就把线程处理完的结果通过信号发送到主界面的进程,主界面在接收到这个消息后,根据接收到的消息更新主界面
class btn2Thread(QThread): # 声明一个信号 update_ui_signal=pyqtSignal(str) def __init__(self): super(btn2Thread,self).__init__() def run(self): # 以下为一通逻辑操作,比如查询数据库 time.sleep(10) # 根据查询数据库的结果,比如查询到200,发送信号 self.update_ui_signal.emit((str(200)))
至此解决了界面卡死的问题,以下为完整代码
import sys from PyQt5.Qt import * import time class btn2Thread(QThread): # 声明一个信号 update_ui_signal=pyqtSignal(str) def __init__(self): super(btn2Thread,self).__init__() def run(self): # 以下为一通逻辑操作,比如查询数据库 time.sleep(10) # 根据查询数据库的结果,比如查询到200,发送信号 self.update_ui_signal.emit((str(200))) class Window(QWidget): def __init__(self): super().__init__() self.setWindowTitle("更新界面案例") self.resize(300, 200) self.move(400, 250) def setup_ui(self): self.label = QLabel(self) self.label.setText("当前人数: 100") self.label.move(100, 50) self.btn1=QPushButton(self) self.btn1.setText("按钮1") self.btn1.move(50,125) self.btn1.clicked.connect(self.btn1_method) self.btn2=QPushButton(self) self.btn2.setText("按钮2") self.btn2.move(165,125) self.btn2.clicked.connect(self.btn2_method) def btn1_method(self): # 以下为一通逻辑操作 time.sleep(10) #根据上面逻辑操作的结果,更新界面 self.label.setText("当前人数: 200") def btn2_method(self): self.btn2Thread_object=btn2Thread() self.btn2Thread_object.start() self.btn2Thread_object.update_ui_signal.connect(self.update_label) def update_label(self,str1): self.label.setText("当前人数: %s"%(str1)) if __name__ == "__main__": app = QApplication(sys.argv) window = Window() window.setup_ui() window.show() sys.exit(app.exec_())
到此这篇关于PyQt界面阻塞卡死问题的解决的文章就介绍到这了,更多相关PyQt界面阻塞卡死内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!