目錄
1、QTimer計時器類
2、QThread多執行緒類
3、事件處理類
一般情況下,應用程式都是單執行緒運行的,但是對于GUI程式來說,單執行緒有時候滿足不了需求,例如,如果需要執行一個特別耗時的操作,在執行程序中整個程式就會卡頓,效果就非常不理想或者Windows系統也認為程式運行出錯,自動關閉了程式,要解決這種問題就涉及多執行緒的知識,
一般來說,多執行緒技術涉及三種方法,其中第一種是使用計時器模塊QTimer;第二種是使用多執行緒模塊QThread;最后是使用事件處理的功能,
1、QTimer計時器類
如果要在應用程式中周期性地進行某項操作,比如周期性地檢測主機的CPU值,則需要用到QTimer(定時器),QTimer類提供了重復的和單次的定時器,要使用定時器,需要先創建一個QTimer實體,將其timeout信號連接到相應的槽,并呼叫start(),然后,定時器會以恒定的間隔發出timeout信號,
當視窗控制元件收到timeout信號后,它就會停止這個定時器,這是在圖形用戶界面中實作復雜作業的一個典型方法,隨著技術的進步,多執行緒在越來越多的平臺上被使用,最終QTimer物件會被執行緒所替代,
QTimer類中的常用方法如下表所示:

QTimer類中的常用信號如下表所示:

通過一個示例,了解QTimer計時器類的使用方法,效果如下所示:


示例中,初始化一個定時器,把定時器的timeout信號與showTime()槽函式連接起來,使用連接的槽函式顯示當前時間,并在標簽上顯示系統現在的時間,單擊“開始"按鈕,啟動定時器,并使"開始"按鈕失效,單擊“結束"按鈕,停止定時器,并使“結束"按鈕失效,
實作代碼如下所示:
from PyQt5.QtWidgets import QWidget, QPushButton , QApplication ,QListWidget, QGridLayout , QLabel
from PyQt5.QtCore import QTimer ,QDateTime
import sys
class WinForm(QWidget):
def __init__(self,parent=None):
super(WinForm,self).__init__(parent)
self.setWindowTitle("QTimer demo")
self.listFile= QListWidget()
self.label = QLabel('顯示當前時間')
self.startBtn = QPushButton('開始')
self.endBtn = QPushButton('結束')
layout = QGridLayout(self)
# 初始化一個定時器
self.timer = QTimer(self)
# showTime()方法
self.timer.timeout.connect(self.showTime)
layout.addWidget(self.label,0,0,1,2)
layout.addWidget(self.startBtn,1,0)
layout.addWidget(self.endBtn,1,1)
self.startBtn.clicked.connect( self.startTimer)
self.endBtn.clicked.connect( self.endTimer)
self.setLayout(layout)
def showTime(self):
# 獲取系統現在的時間
time = QDateTime.currentDateTime()
# 設定系統時間顯示格式
timeDisplay = time.toString("yyyy-MM-dd hh:mm:ss dddd");
# 在標簽上顯示時間
self.label.setText( timeDisplay )
def startTimer(self):
# 設定計時間隔并啟動
self.timer.start(1000)
self.startBtn.setEnabled(False)
self.endBtn.setEnabled(True)
def endTimer(self):
self.timer.stop()
self.startBtn.setEnabled(True)
self.endBtn.setEnabled(False)
if __name__ == "__main__":
app = QApplication(sys.argv)
form = WinForm()
form.show()
sys.exit(app.exec_())
2、QThread多執行緒類
QThread是Qt執行緒類中最核心的底層類,由于PyQt的跨平臺特性,QThread要隱藏所有與平臺相關的代碼,
在使用執行緒時可以直接得到Thread實體,呼叫其start()函式即可啟動執行緒,執行緒啟動之后,會自動呼叫其實作的run方法,該方法就是執行緒的執行函式,
業務的執行緒任務就寫在run()函式中,當run()退出之后執行緒基本就結束了,QThread有started和finished信號,可以為這兩個信號指定槽函式,在執行緒啟動和結束時執行一段代碼進行資源的初始化和釋放操作,更靈活的使用方法是,在自定義的QThread實體中自定義信號,并將信號連接到指定的槽函式,當滿足一定的業務條件后發射此信號,
QThread類中的常用方法如下表所示:

QThread類中的常用信號如下表所示:

通過一個示例,了解QThread多執行緒類的使用方法,效果如下所示:

示例中,在主界面中有一個用于顯示時間的LCD數字面板,還有一個用于啟動任務的按鈕,用戶單擊"測驗"按鈕后,將開始一次非常耗時的計算(在程式中用一個2000 000 000次的回圈來模擬這次非常耗時的作業,在真實的程式中可能是一個網路下載操作,從網路上下載一個很大的視頻檔案),同時LCD數字面板開始顯示所用的毫秒數,并通過一個計時器進行更新,但是單擊”測驗“按鈕后可見視窗卡死無法操作,此時在PyQt中所有的視窗都在UI主執行緒中(就是執行了QApplication.exec()的執行緒),在這個執行緒中執行耗時的操作會阻塞UI執行緒,從而讓視窗停止回應,如果視窗長時間沒有回應,則會影響用戶體驗,更嚴重的會導致程式崩潰,所以,為了避免出現這樣的問題,要使用QThread開啟一個新的執行緒,在這個執行緒中完成耗時的操作,
實作代碼如下所示:
import sys
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(2000000000):
pass
# 回圈完畢后發出信號
self.trigger.emit()
def countTime():
global sec
sec += 1
# LED顯示數字+1
lcdNumber.display(sec)
def work():
# 計時器每秒計數
timer.start(1000)
# 計時開始
workThread.start()
# 當獲得回圈完畢的信號時,停止計數
workThread.trigger.connect(timeStop)
def timeStop():
timer.stop()
print("運行結束用時",lcdNumber.value())
global sec
sec=0
if __name__ == "__main__":
app = QApplication(sys.argv)
top = QWidget()
top.resize(300,120)
# 垂直布局類QVBoxLayout
layout = QVBoxLayout(top)
# 加個顯示屏
lcdNumber = QLCDNumber()
layout.addWidget(lcdNumber)
button = QPushButton("測驗")
layout.addWidget(button)
timer = QTimer()
workThread = WorkThread()
button.clicked.connect(work)
# 每次計時結束,觸發 countTime
timer.timeout.connect(countTime)
top.show()
sys.exit(app.exec_())
3、事件處理類
PyQt為事件處理提供了兩種機制:高級的信號與槽機制以及低級的事件處理程式,本篇文博只介紹低級的事件處理程式即:processEvents()函式的使用方法,它的作用是處理事件,簡單地說,就是重繪頁面,
對于執行很耗時的程式來說,由于PyQt需要等待程式執行完畢才能進行下一步,這個程序表現在界面上就是卡頓,而如果在執行這個耗時程式時不斷地運行
QApplication.processEvents(),那么就可以實作一邊執行耗時程式,一邊重繪頁面的功能,給人的感覺就是程式運行很流暢,
因此QApplication.processEvents()的使用方法就是,在主函式執行耗時操作的地方,加入QApplication.processEvents(),
通過一個示例,了解事件處理類的使用方法,效果如下所示:

實作代碼如下所示:
from PyQt5.QtWidgets import QWidget, QPushButton , QApplication ,QListWidget, QGridLayout
import sys
import time
class WinForm(QWidget):
def __init__(self,parent=None):
super(WinForm,self).__init__(parent)
self.setWindowTitle("實時重繪界面例子")
self.listFile= QListWidget()
self.btnStart = QPushButton('開始')
layout = QGridLayout(self)
layout.addWidget(self.listFile,0,0,1,2)
layout.addWidget(self.btnStart,1,1)
self.btnStart.clicked.connect( self.slotAdd)
self.setLayout(layout)
def slotAdd(self):
for n in range(10):
str_n='File index {0}'.format(n)
self.listFile.addItem(str_n)
QApplication.processEvents()
time.sleep(1)
if __name__ == "__main__":
app = QApplication(sys.argv)
form = WinForm()
form.show()
sys.exit(app.exec_())
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/310795.html
標籤:python
上一篇:如何在C 中按字母順序排列堆疊?
