python PyQt5事件機(jī)制和定時(shí)器原理分析及用法詳解
PyQt5事件機(jī)制
PyQt為事件處理提供了兩種機(jī)制:高級(jí)的信號(hào)與槽機(jī)制,以及低級(jí)的事件處理機(jī)制。信號(hào)與槽可以說是對(duì)事件處理機(jī)制的高級(jí)封裝。事件機(jī)制更偏向于底層。
常見事件類型:
鍵盤事件:按鍵按下和松開。
鼠標(biāo)事件:鼠標(biāo)指針移動(dòng),鼠標(biāo)按下和松開。
拖放事件:用鼠標(biāo)進(jìn)行拖放。
滾輪事件:鼠標(biāo)滾輪滾動(dòng)。
繪屏事件:重繪屏幕的某些部分。
定時(shí)事件:定時(shí)器到時(shí)。
焦點(diǎn)事件:鍵盤焦點(diǎn)移動(dòng)。
進(jìn)入/離開事件:鼠標(biāo)指針移入Widget內(nèi),或者移出。
移動(dòng)事件:Widget的位置改變。
大小改變事件:Widget的大小改變。
顯示/隱藏事件:Widget顯示和隱藏。
窗口事件:窗口是否為當(dāng)前窗口。
PyQt提供了如下5種事件處理和過濾方法(有弱到強(qiáng)):
重新實(shí)現(xiàn)事件函數(shù),比如mousePressEvent(),keyPressEvent()等等。
重新實(shí)現(xiàn)QObject.event()。
安裝時(shí)間過濾器。
在QApplication中安裝事件過濾器。
重新實(shí)現(xiàn)QAppliction的notifiy()方法。
PyQt5事件處理的API
PyQt5事件機(jī)制演練
import sys from PyQt5.Qt import * #通過繼承,重新notify方法 #事件會(huì)分發(fā)給對(duì)象里面的notify方法 class App(QApplication): #notify第一個(gè)參數(shù)是控件類型(事件接收者),第二個(gè)是事件類型 def notify(self, recevier, evt): #notify會(huì)監(jiān)控所有的事件,對(duì)事件進(jìn)行分發(fā)。為了打印鼠標(biāo)點(diǎn)擊按鈕產(chǎn)生的事件,我們進(jìn)行了過濾 #過濾事件接收者是按鈕,事件類型是鼠標(biāo)按鈕按下 #evt屬于QEvent類型。QEvent類型里面有個(gè)type方法,用來判斷事件類型 if recevier.inherits("QPushButton") and evt.type() == QEvent.MouseButtonPress: print(recevier, evt) #優(yōu)先調(diào)用子類notify方法,由于我們沒有寫具體功能,什么也做不了,會(huì)報(bào)錯(cuò),為了防止程序報(bào)錯(cuò),需要將父類的notify方法返回 #這行代碼就是負(fù)責(zé)分發(fā)的 return super().notify(recevier, evt) #寫個(gè)子類,過濾event事件類型 class Btn(QPushButton): #事件會(huì)分發(fā)給按鈕對(duì)象的event方法,event里面包含很多事件 def event(self, evt): if evt.type() == QEvent.MouseButtonPress: print(evt) #根據(jù)事件類型再次進(jìn)行分發(fā),根據(jù)不同事件調(diào)用不同事件函數(shù) return super().event(evt) #重寫鼠標(biāo)被按下事件函數(shù) def mousePressEvent(self, *args, **kwargs): print("鼠標(biāo)被按下了......") #返回父類鼠標(biāo)事件函數(shù),進(jìn)而發(fā)射信號(hào)給槽,調(diào)用槽函數(shù) #如果不返回,則不會(huì)發(fā)射信號(hào)給槽 return super().mousePressEvent(*args, **kwargs) app = App(sys.argv) window = QWidget() #設(shè)置主題 window.setWindowTitle("事件機(jī)制") btn = Btn(window) btn.setText("按鈕") btn.move(100, 100) def cao(): print("按鈕被點(diǎn)擊了") #按鍵按下 btn.pressed.connect(cao) window.show() sys.exit(app.exec_())
運(yùn)行
點(diǎn)擊按鈕
可見事件被觸發(fā)
PyQt5定時(shí)器
在基于PyQt5的應(yīng)用程序開發(fā)過程中經(jīng)常會(huì)遇到一些需要循環(huán)執(zhí)行的任務(wù),即定時(shí)多長時(shí)間任務(wù)循環(huán)一次。
常用于數(shù)據(jù)庫定時(shí)更新、界面刷新、內(nèi)存清理、腳本任務(wù)運(yùn)行、進(jìn)度條等需要定時(shí)更新的程序段,小到某一參數(shù)的定時(shí)更新,大到整個(gè)線程任務(wù)的更新、程序段的循環(huán)定時(shí)執(zhí)行。
本文將詳細(xì)介紹如何在PyQt5中使用定時(shí)器,包括定時(shí)器的基本原理、創(chuàng)建和使用定時(shí)器的方法以及一些實(shí)際應(yīng)用案例。
定時(shí)器的操作方法有兩種
方法一:利用每個(gè)對(duì)象包含的timerEvent函數(shù)
方法二:利用定時(shí)器模塊 需要 from PyQt5.QtCore import QTimer
(1)利用每個(gè)對(duì)象包含的timerEvent函數(shù)
API介紹已經(jīng)案例演示
# 0. 導(dǎo)入需要的包和模塊 from PyQt5.Qt import * import sys #自定義一個(gè)類繼承QObejct # class MyObject(QObject): # def timerEvent(self, evt): #重寫對(duì)象的定時(shí)器函數(shù) # print(evt, "1") #自定義個(gè)類繼承QLabel,可以重寫父類方法,尤其是timerEvent對(duì)象的定時(shí)器函數(shù) class MyLabel(QLabel): #增加參數(shù)接收*args, **kwargs def __init__(self, *args, **kwargs): # 當(dāng)我們繼承某個(gè)類時(shí),需要調(diào)用父類構(gòu)造方法 #加載父類初始化方法 super().__init__(*args, **kwargs) self.setText("10") self.move(235, 235) self.setStyleSheet("font-size: 28px;") #設(shè)置標(biāo)簽上展示的初始數(shù)字 def setSec(self, sec): self.setText(str(sec)) def startMyTimer(self, ms): #可以創(chuàng)建多個(gè),每個(gè)startTimer返回的id不同 #每個(gè)一定的時(shí)間,就會(huì)自動(dòng)執(zhí)行對(duì)象中的timerEvent函數(shù) #參數(shù)1 間隔時(shí)間,單位毫秒 self.timer_id = self.startTimer(ms,timerType=Qt.PreciseTimer) #啟動(dòng)對(duì)象定時(shí)器函數(shù) def timerEvent(self, *args, **kwargs): print("倒計(jì)時(shí)進(jìn)行中") # 1. 獲取當(dāng)前的標(biāo)簽的內(nèi)容 current_sec = int(self.text()) current_sec -= 1 #將內(nèi)容以字符串形式展示,整形數(shù)據(jù)沒法直接放進(jìn)來 self.setText(str(current_sec)) #當(dāng)前數(shù)字減為0時(shí),停止定時(shí)器 if current_sec == 0: print("倒計(jì)時(shí)停止") # 釋放對(duì)象的定時(shí)器函數(shù) self.killTimer(self.timer_id) class MyWidget(QWidget): def startMyTimer(self, ms): #可以創(chuàng)建多個(gè),每個(gè)startTimer返回的id不同 #每個(gè)一定的時(shí)間,就會(huì)自動(dòng)執(zhí)行對(duì)象中的timerEvent函數(shù) #參數(shù)1 間隔時(shí)間,單位毫秒 self.widget_id = self.startTimer(ms,timerType=Qt.PreciseTimer) #啟動(dòng)對(duì)象定時(shí)器函數(shù) def timerEvent(self, *args, **kwargs): #獲取當(dāng)前窗口的高和寬 current_w = self.width() current_h = self.height() #定時(shí)器每執(zhí)行一次,窗口長和高都加10 self.resize(current_w + 10, current_h + 10) print("當(dāng)前窗口高度", current_h) #設(shè)置當(dāng)前窗口高度達(dá)到550時(shí),停止定時(shí)器 if current_h == 550: print("widget停止") # 釋放對(duì)象的定時(shí)器函數(shù) self.killTimer(self.widget_id) if __name__ == '__main__': # 1. 創(chuàng)建一個(gè)應(yīng)用程序?qū)ο? app = QApplication(sys.argv) # 2. 控件的操作 # 2.1 創(chuàng)建控件 window = MyWidget() # 2.2 設(shè)置控件 window.setWindowTitle("QObject定時(shí)器的使用") window.resize(500, 500) window.startMyTimer(1000) #創(chuàng)建第二個(gè)控件 label = MyLabel(window) label.setSec(10) label.startMyTimer(500) # 2.3 展示控件 window.show() # 3. 應(yīng)用程序的執(zhí)行, 進(jìn)入到消息循環(huán) sys.exit(app.exec_())
運(yùn)行
當(dāng)?shù)竭_(dá)臨界值,定時(shí)器停止
(2)利用定時(shí)器模塊QTimer
需要導(dǎo)包 from PyQt5.QtCore import QTimer
QTimer 的事件可以通過 QTimer.timeout.connect() 信號(hào)槽綁定到對(duì)應(yīng)的處理函數(shù)上。
例如,在下面的示例中,定義了一個(gè) onTimer() 函數(shù),每當(dāng)定時(shí)器時(shí)間到達(dá)時(shí),就會(huì)執(zhí)行這個(gè)函數(shù)。
要啟動(dòng) QTimer 定時(shí)器,需要調(diào)用 QTimer.setInterval() 方法,并傳入時(shí)間間隔,單位為毫秒(ms)。
例如,傳入 1000 表示每隔 1000 毫秒(即 1 秒)會(huì)觸發(fā)一次 operate()。需要注意的是,定時(shí)器不僅僅是觸發(fā)一次,而是持續(xù)按照設(shè)定的時(shí)間間隔觸發(fā),直到調(diào)用 QTimer.stop() 方法停止。
import sys from PyQt5.Qt import * class win(QWidget): #創(chuàng)建一個(gè)類,為了集成控件 # 增加參數(shù)接收*args, **kwargs def __init__(self, *args, **kwargs): # 當(dāng)我們繼承某個(gè)類時(shí),需要調(diào)用父類構(gòu)造方法 super().__init__(*args, **kwargs) self.setWindowTitle('定時(shí)器的使用') self.resize(300,300) self.num=0 self.setup_ui() def setup_ui(self): #添加個(gè)標(biāo)簽,初始化標(biāo)簽 self.lable = QLabel(self) self.lable.move(120,120) self.lable.setStyleSheet("font-size: 28px;") self.timer = QTimer(self) # 初始化一個(gè)定時(shí)器 # 設(shè)置計(jì)時(shí)間隔;單位毫秒 self.timer.setInterval(1000) self.timer.timeout.connect(self.operate) # 每次計(jì)時(shí)到時(shí)間時(shí)發(fā)出信號(hào) #啟動(dòng)定時(shí)器,也可以在這里設(shè)置時(shí)間間隔,例如:self.timer.start(1000) 表示每秒執(zhí)行一次 self.timer.start() #定時(shí)器要執(zhí)行的動(dòng)作 def operate(self): self.num=self.num+1 print(self.num) #動(dòng)態(tài)設(shè)置標(biāo)簽顯示數(shù)字 self.lable.setText(str(self.num)) #設(shè)置定時(shí)器停止閾值 if self.num == 5: print("計(jì)時(shí)停止") self.timer.stop() if __name__=='__main__': app=QApplication(sys.argv) #創(chuàng)建應(yīng)用 window=win() window.show() sys.exit(app.exec_())
運(yùn)行
當(dāng)num數(shù)值增加到5時(shí),定時(shí)器停止
以上就是python PyQt5事件機(jī)制和定時(shí)器原理分析及用法詳解的詳細(xì)內(nèi)容,更多關(guān)于PyQt5事件機(jī)制和定時(shí)器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
通過Python 獲取Android設(shè)備信息的輕量級(jí)框架
今天跟大家分享一下,如何通過Python實(shí)現(xiàn)一個(gè)輕量級(jí)的庫來獲取電腦上連接的Android設(shè)備信息,需要的朋友參考下吧2017-12-12利用 Python 實(shí)現(xiàn)多任務(wù)進(jìn)程
這篇文章主要介紹如何利用 Python 實(shí)現(xiàn)多任務(wù)進(jìn)程,正在執(zhí)行的程序,由程序、數(shù)據(jù)和進(jìn)程控制塊組成,是正在執(zhí)行的程序,程序的一次執(zhí)行過程,是資源調(diào)度的基本單位。下面就來詳細(xì)介紹改內(nèi)容,需要的朋友可以參考一下2021-10-10Python實(shí)現(xiàn)郵件自動(dòng)下載的示例詳解
這篇文章主要為大家詳細(xì)介紹了如何利用Python語言實(shí)現(xiàn)郵件自動(dòng)下載以及附件解析功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-07-07使用APScheduler3.0.1 實(shí)現(xiàn)定時(shí)任務(wù)的方法
今天小編就為大家分享一篇使用APScheduler3.0.1 實(shí)現(xiàn)定時(shí)任務(wù)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-07-07淺析Python與Java和C之間有哪些細(xì)微區(qū)別
這篇文章主要介紹了Python與Java和C之間有哪些細(xì)微區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08Python中l(wèi)ist查詢及所需時(shí)間計(jì)算操作示例
這篇文章主要介紹了Python中l(wèi)ist查詢及所需時(shí)間計(jì)算操作,涉及Python列表list遍歷、查詢及時(shí)間消耗計(jì)算相關(guān)操作技巧,需要的朋友可以參考下2018-06-06