PyQt5 pyqt多線程操作入門
首先來看一個(gè)例子:
# 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顯示數(shù)字+1
def work():
timer.start(1000) #計(jì)時(shí)器每秒計(jì)數(shù)
for i in range(2000000000):
pass
timer.stop()
app=QApplication([])
top=QWidget()
layout=QVBoxLayout(top) #垂直布局類QVBoxLayout;
lcdNumber=QLCDNumber() #加個(gè)顯示屏
layout.addWidget(lcdNumber)
button=QPushButton("測試")
layout.addWidget(button)
timer=QTimer()
timer.timeout.connect(setTime) #每次計(jì)時(shí)結(jié)束,觸發(fā)setTime
button.clicked.connect(work)
top.show()
app.exec()
我們的主界面有一個(gè)用于顯示時(shí)間的 LCD 數(shù)字面板還有一個(gè)用于啟動(dòng)任務(wù)的按鈕。程序的目的是用戶點(diǎn)擊按鈕,開始一個(gè)非常耗時(shí)的運(yùn)算(程序中我們以一個(gè) 2000000000 次的循環(huán)來替代這個(gè)非常耗時(shí)的工作,在真實(shí)的程序中,這可能是一個(gè)網(wǎng)絡(luò)訪問,可能是需要復(fù)制一個(gè)很大的文件或者其它任務(wù)),同時(shí) LCD 開始顯示逝去的毫秒數(shù)。毫秒數(shù)通過一個(gè)計(jì)時(shí)器QTimer進(jìn)行更新。計(jì)算完成后,計(jì)時(shí)器停止。這是一個(gè)很簡單的應(yīng)用,也看不出有任何問題。但是當(dāng)我們開始運(yùn)行程序時(shí),問題就來了:點(diǎn)擊按鈕之后,程序界面直接停止響應(yīng),直到循環(huán)結(jié)束才開始重新更新,于是計(jì)時(shí)器使用顯示0。
有經(jīng)驗(yàn)的開發(fā)者立即指出,這里需要使用線程。這是因?yàn)?Qt 中所有界面都是在 UI 線程中(也被稱為主線程,就是執(zhí)行了QApplication::exec()的線程),在這個(gè)線程中執(zhí)行耗時(shí)的操作(比如那個(gè)循環(huán)),就會(huì)阻塞 UI 線程,從而讓界面停止響應(yīng)。界面停止響應(yīng),用戶體驗(yàn)自然不好,不過更嚴(yán)重的是,有些窗口管理程序會(huì)檢測到你的程序已經(jīng)失去響應(yīng),可能會(huì)建議用戶強(qiáng)制停止程序,這樣一來你的程序可能就此終止,任務(wù)再也無法完成。所以,為了避免這一問題,我們要使用 QThread 開啟一個(gè)新的線程:
# 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() #循環(huán)完畢后發(fā)出信號(hào)
def countTime():
global sec
sec+=1
lcdNumber.display(sec) #LED顯示數(shù)字+1
def work():
timer.start(1000) #計(jì)時(shí)器每秒計(jì)數(shù)
workThread.start() #計(jì)時(shí)開始
workThread.trigger.connect(timeStop) #當(dāng)獲得循環(huán)完畢的信號(hào)時(shí),停止計(jì)數(shù)
def timeStop():
timer.stop()
print("運(yùn)行結(jié)束用時(shí)",lcdNumber.value())
global sec
sec=0
app=QApplication([])
top=QWidget()
layout=QVBoxLayout(top) #垂直布局類QVBoxLayout;
lcdNumber=QLCDNumber() #加個(gè)顯示屏
layout.addWidget(lcdNumber)
button=QPushButton("測試")
layout.addWidget(button)
timer=QTimer()
workThread=WorkThread()
button.clicked.connect(work)
timer.timeout.connect(countTime) #每次計(jì)時(shí)結(jié)束,觸發(fā)setTime
top.show()
app.exec()
我增加了一個(gè)WorkerThread類。WorkerThread繼承自QThread類,重寫了其run()函數(shù)??梢哉J(rèn)為,run()函數(shù)就是新的線程需要執(zhí)行的代碼。在這里就是要執(zhí)行這個(gè)循環(huán),然后發(fā)出計(jì)算完成的信號(hào)。而在按鈕點(diǎn)擊的槽函數(shù)中,使用work()中的workThread.start()函數(shù)啟動(dòng)一個(gè)線程(注意,這里不是run()函數(shù))。再次運(yùn)行程序,你會(huì)發(fā)現(xiàn)現(xiàn)在界面已經(jīng)不會(huì)被阻塞了。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python 隨機(jī)生成中文驗(yàn)證碼的實(shí)例代碼
Python 隨機(jī)生成中文驗(yàn)證碼的實(shí)例代碼,需要的朋友可以參考一下2013-03-03
Matlab如何實(shí)現(xiàn)矩陣復(fù)制擴(kuò)充
這篇文章主要介紹了使用Matlab實(shí)現(xiàn)矩陣復(fù)制擴(kuò)充的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
python:接口間數(shù)據(jù)傳遞與調(diào)用方法
今天小編就為大家分享一篇python:接口間數(shù)據(jù)傳遞與調(diào)用方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-12-12
對(duì)python中兩種列表元素去重函數(shù)性能的比較方法
今天小編就為大家分享一篇對(duì)python中兩種列表元素去重函數(shù)性能的比較方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-06-06
Python可以實(shí)現(xiàn)棧的結(jié)構(gòu)嗎
在本篇文章里小編給各位整理的是關(guān)于Python實(shí)現(xiàn)棧的結(jié)構(gòu)的條件的相關(guān)知識(shí)點(diǎn),有需要的朋友們可以學(xué)習(xí)下。2020-05-05

