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

轉載:翻滾吧挨踢男網絡

首先來看一個例子:app

# 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()函數)。再次運行程序,你會發現如今界面已經不會被阻塞了。佈局

相關文章
相關標籤/搜索