Python

pyqt5教程(十一)多线程防阻塞

2017-05-20  本文已影响553人  交易狗二哈

一、

当我们设计的界面在处理比较长时间的任务时,就会出现阻塞,出现程序未响应,导致程序停止的情况,例如这个百度图片下载器
所以我们应把主线程与工作线程分离,以免主循环阻塞,造成程序停止响应

二、例子

from PyQt5.QtCore import *  
from PyQt5.QtGui import *  
from PyQt5.QtWidgets import *
import sys

class Example(QWidget):

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

        self.t = 0

        window = QWidget()
        vbox = QVBoxLayout(window)
        #vbox = QVBoxLayout(window)

        lcdNumber = QLCDNumber()
        button = QPushButton("测试")
        vbox.addWidget(lcdNumber)
        vbox.addWidget(button)

        self.timer = QTimer()
        
        button.clicked.connect(self.work)
        self.timer.timeout.connect(self.setTime)

        self.setLayout(vbox)
        self.show()

    def setTime(self):
        self.t += 1
        self.lcdNumber.display(self.t)

    def work(self):
        self.timer.start(10000)
        for i in range(200000000):
            pass
        self.timer.stop()
        
        
if __name__ == "__main__":        
    app = QApplication(sys.argv)
    th = Example()
    sys.exit(app.exec_())

运行这个程序,当我们点击测试,进行较长时间的任务时,程序就无法选中了,最终停止运行。

三、多线程

下面用多线写法解决该问题

from PyQt5.QtCore import *  
from PyQt5.QtGui import *  
from PyQt5.QtWidgets import *
import sys

class Example(QWidget):

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

        self.t = 0

        window = QWidget()
        vbox = QVBoxLayout(window)
        #vbox = QVBoxLayout(window)

        self.lcdNumber = QLCDNumber()
        button = QPushButton("测试")
        vbox.addWidget(self.lcdNumber)
        vbox.addWidget(button)

        self.timer = QTimer()
        
        button.clicked.connect(self.Work)
        self.timer.timeout.connect(self.CountTime)

        self.setLayout(vbox)
        self.show()

    def CountTime(self):
        self.t += 1
        self.lcdNumber.display(self.t)

    def Work(self):
        self.timer.start(1000)
        self.thread = RunThread()
        self.thread.start()
        self.thread.trigger.connect(self.TimeStop)

    def TimeStop(self):
        self.timer.stop()
        print("运行结束用时",self.lcdNumber.value())
        self.t = 0
        

class RunThread(QThread):
    # python3,pyqt5与之前的版本有些不一样
    #  通过类成员对象定义信号对象
    # _signal = pyqtSignal(str)

    trigger = pyqtSignal()
 
    def __init__(self, parent=None):
        super(RunThread, self).__init__()

 
    def __del__(self):
        self.wait() 

    def run(self):
        # 处理你要做的业务逻辑,这里是通过一个回调来处理数据,这里的逻辑处理写自己的方法
        # wechat.start_auto(self.callback)
        # self._signal.emit(msg);  可以在这里写信号焕发
        for i in range(203300030):  
            pass  
        self.trigger.emit()
        # self._signal.emit(msg)

    def callback(self, msg):
        # 信号焕发,我是通过我封装类的回调来发起的
        # self._signal.emit(msg)
        pass

        

if __name__ == "__main__":
    app = QApplication(sys.argv)
    th = Example()
    sys.exit(app.exec_())

从此以后,我们可以开始写很多应用了

上一篇 下一篇

猜你喜欢

热点阅读