python PyQt5事件機(jī)制和定時(shí)器原理分析及用法詳解
PyQt5事件機(jī)制
PyQt為事件處理提供了兩種機(jī)制:高級(jí)的信號(hào)與槽機(jī)制,以及低級(jí)的事件處理機(jī)制。信號(hào)與槽可以說(shuō)是對(duì)事件處理機(jī)制的高級(jí)封裝。事件機(jī)制更偏向于底層。
常見(jiàn)事件類型:
鍵盤事件:按鍵按下和松開(kāi)。
鼠標(biāo)事件:鼠標(biāo)指針移動(dòng),鼠標(biāo)按下和松開(kāi)。
拖放事件:用鼠標(biāo)進(jìn)行拖放。
滾輪事件:鼠標(biāo)滾輪滾動(dòng)。
繪屏事件:重繪屏幕的某些部分。
定時(shí)事件:定時(shí)器到時(shí)。
焦點(diǎn)事件:鍵盤焦點(diǎn)移動(dòng)。
進(jìn)入/離開(kāi)事件:鼠標(biāo)指針移入Widget內(nèi),或者移出。
移動(dòng)事件:Widget的位置改變。
大小改變事件:Widget的大小改變。
顯示/隱藏事件:Widget顯示和隱藏。
窗口事件:窗口是否為當(dāng)前窗口。
PyQt提供了如下5種事件處理和過(guò)濾方法(有弱到強(qiáng)):
重新實(shí)現(xiàn)事件函數(shù),比如mousePressEvent(),keyPressEvent()等等。
重新實(shí)現(xiàn)QObject.event()。
安裝時(shí)間過(guò)濾器。
在QApplication中安裝事件過(guò)濾器。
重新實(shí)現(xiàn)QAppliction的notifiy()方法。


PyQt5事件處理的API

PyQt5事件機(jī)制演練
import sys
from PyQt5.Qt import *
#通過(guò)繼承,重新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)行了過(guò)濾
#過(guò)濾事件接收者是按鈕,事件類型是鼠標(biāo)按鈕按下
#evt屬于QEvent類型。QEvent類型里面有個(gè)type方法,用來(lái)判斷事件類型
if recevier.inherits("QPushButton") and evt.type() == QEvent.MouseButtonPress:
print(recevier, evt)
#優(yōu)先調(diào)用子類notify方法,由于我們沒(méi)有寫(xiě)具體功能,什么也做不了,會(huì)報(bào)錯(cuò),為了防止程序報(bào)錯(cuò),需要將父類的notify方法返回
#這行代碼就是負(fù)責(zé)分發(fā)的
return super().notify(recevier, evt)
#寫(xiě)個(gè)子類,過(guò)濾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)
#重寫(xiě)鼠標(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)擊按鈕
可見(jiàn)事件被觸發(fā)

PyQt5定時(shí)器
在基于PyQt5的應(yīng)用程序開(kāi)發(fā)過(guò)程中經(jīng)常會(huì)遇到一些需要循環(huán)執(zhí)行的任務(wù),即定時(shí)多長(zhǎng)時(shí)間任務(wù)循環(huán)一次。
常用于數(shù)據(jù)庫(kù)定時(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): #重寫(xiě)對(duì)象的定時(shí)器函數(shù)
# print(evt, "1")
#自定義個(gè)類繼承QLabel,可以重寫(xiě)父類方法,尤其是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ù)沒(méi)法直接放進(jìn)來(lái)
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í)行一次,窗口長(zhǎng)和高都加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 的事件可以通過(guò) 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基礎(chǔ)之with語(yǔ)句和上下文管理器詳解
這篇文章主要為大家詳細(xì)介紹了Python中with語(yǔ)句和上下文管理器的具體使用方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-04-04
通過(guò)Python 獲取Android設(shè)備信息的輕量級(jí)框架
今天跟大家分享一下,如何通過(guò)Python實(shí)現(xiàn)一個(gè)輕量級(jí)的庫(kù)來(lái)獲取電腦上連接的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í)行過(guò)程,是資源調(diào)度的基本單位。下面就來(lái)詳細(xì)介紹改內(nèi)容,需要的朋友可以參考一下2021-10-10
Python實(shí)現(xiàn)郵件自動(dòng)下載的示例詳解
這篇文章主要為大家詳細(xì)介紹了如何利用Python語(yǔ)言實(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ì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07
淺析Python與Java和C之間有哪些細(xì)微區(qū)別
這篇文章主要介紹了Python與Java和C之間有哪些細(xì)微區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
Python中l(wèi)ist查詢及所需時(shí)間計(jì)算操作示例
這篇文章主要介紹了Python中l(wèi)ist查詢及所需時(shí)間計(jì)算操作,涉及Python列表list遍歷、查詢及時(shí)間消耗計(jì)算相關(guān)操作技巧,需要的朋友可以參考下2018-06-06

