PyQt5學習筆記14----初識pyqt多線程操作


轉載:翻滾吧挨踢男

首先來看一個例子:

# coding=utf-8
__author__ = 'a359680405'

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

global sec
sec=0
def setTime():
    global  sec
    sec+=1
    lcdNumber.display(sec)          #LED顯示數字+1

def work():
    timer.start(1000)               #計時器每秒計數
    for i in range(2000000000):
       pass
    timer.stop()

app=QApplication([])
top=QWidget()
layout=QVBoxLayout(top)             #垂直布局類QVBoxLayout;
lcdNumber=QLCDNumber()              #加個顯示屏
layout.addWidget(lcdNumber)
button=QPushButton("測試")
layout.addWidget(button)

timer=QTimer()
timer.timeout.connect(setTime)      #每次計時結束,觸發setTime
button.clicked.connect(work)

top.show()
app.exec()

    我們的主界面有一個用於顯示時間的 LCD 數字面板還有一個用於啟動任務的按鈕。程序的目的是用戶點擊按鈕,開始一個非常耗時的運算(程序中我們以一個 2000000000 次的循環來替代這個非常耗時的工作,在真實的程序中,這可能是一個網絡訪問,可能是需要復制一個很大的文件或者其它任務),同時 LCD 開始顯示逝去的毫秒數。毫秒數通過一個計時器QTimer進行更新。計算完成后,計時器停止。這是一個很簡單的應用,也看不出有任何問題。但是當我們開始運行程序時,問題就來了:點擊按鈕之后,程序界面直接停止響應,直到循環結束才開始重新更新,於是計時器使用顯示0。


      有經驗的開發者立即指出,這里需要使用線程。這是因為 Qt 中所有界面都是在 UI 線程中(也被稱為主線程,就是執行了QApplication::exec()的線程),在這個線程中執行耗時的操作(比如那個循環),就會阻塞 UI 線程,從而讓界面停止響應。界面停止響應,用戶體驗自然不好,不過更嚴重的是,有些窗口管理程序會檢測到你的程序已經失去響應,可能會建議用戶強制停止程序,這樣一來你的程序可能就此終止,任務再也無法完成。所以,為了避免這一問題,我們要使用 QThread 開啟一個新的線程:

# coding=utf-8
__author__ = 'a359680405'

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

global sec
sec=0

class WorkThread(QThread):
    trigger = pyqtSignal()
    def __int__(self):
        super(WorkThread,self).__init__()

    def run(self):
        for i in range(203300030):
            pass
        self.trigger.emit()         #循環完畢后發出信號

def countTime():
    global  sec
    sec+=1
    lcdNumber.display(sec)          #LED顯示數字+1

def work():
    timer.start(1000)               #計時器每秒計數
    workThread.start()              #計時開始
    workThread.trigger.connect(timeStop)   #當獲得循環完畢的信號時,停止計數

def timeStop():
    timer.stop()
    print("運行結束用時",lcdNumber.value())
    global sec
    sec=0

app=QApplication([])
top=QWidget()
layout=QVBoxLayout(top)             #垂直布局類QVBoxLayout;
lcdNumber=QLCDNumber()              #加個顯示屏
layout.addWidget(lcdNumber)
button=QPushButton("測試")
layout.addWidget(button)

timer=QTimer()
workThread=WorkThread()

button.clicked.connect(work)
timer.timeout.connect(countTime)      #每次計時結束,觸發setTime

top.show()
app.exec()

  我增加了一個WorkerThread類。WorkerThread繼承自QThread類,重寫了其run()函數。可以認為,run()函數就是新的線程需要執行的代碼。在這里就是要執行這個循環,然后發出計算完成的信號。而在按鈕點擊的槽函數中,使用work()中的workThread.start()函數啟動一個線程(注意,這里不是run()函數)。再次運行程序,你會發現現在界面已經不會被阻塞了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM