解决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界面阻塞卡死问题_第1张图片

 造成这个现象的原因是,本来软件界面是一直占着主进程的,点击按钮之后,如果按钮执行的是长时间的操作,这个操作就把主进程占住不放了,没有进程来处理软件界面,这个时候界面就会卡死。

所以解决问题的思路就是主进程还是给软件界面,把按钮耗时的工作交给线程去处理,方法有很多,这里用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,ui)