Qt?事件處理機(jī)制的深入理解
1.Qt中事件的來(lái)源,誰(shuí)接收處理。
Qt中事件的來(lái)源有兩個(gè):程序外部和內(nèi)部,多數(shù)情況下來(lái)自操作系統(tǒng),可以通過(guò)bool QEvent::spontaneous() const函數(shù)來(lái)獲知,返回true,事件發(fā)生在應(yīng)用程序之外(系統(tǒng)事件),否則返回false。
事件由QObject類來(lái)接收,是Qt對(duì)象模型的核心,所有需要處理的事件類都必須繼承QObject。
2.事件處理順序
首先QCoreApplication::exec()開(kāi)啟了事件循環(huán),一直到QCoreApplication::exit()被調(diào)用才終止,所以說(shuō)事件循環(huán)是伴隨著Qt程序的整個(gè)運(yùn)行周期,事件被分發(fā)到事件隊(duì)列中,當(dāng)隊(duì)列中有事件時(shí)會(huì)不停的將事件發(fā)送給QObject對(duì)象,隊(duì)列為空時(shí)就阻塞,以下為處理順序。
- sendEvent:使用notify()函數(shù)直接將事件發(fā)送給接收者,發(fā)送事件時(shí)不會(huì)刪除該事件,通常是在棧上面創(chuàng)建事件,它是同步事件。
- postEvent:將事件添加到事件隊(duì)列中,并立即返回;事件必須在堆上分配,因?yàn)樘峤皇录?duì)列將獲得事件的所有權(quán),并在提交后刪除它。在事件發(fā)布后訪問(wèn)該事件是不安全的,它是異步事件。
示例:
void Widget::on_pushButton_clicked() { QKeyEvent eventPress(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier); QApplication::sendEvent(ui->label, &eventPress); } void Widget::on_pushButton_2_clicked() { QKeyEvent *eventPress = new QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier); QApplication::postEvent(ui->label, eventPress); }
點(diǎn)擊上圖中按鈕會(huì)發(fā)送QLabel標(biāo)簽的鍵盤(pán)按下tab鍵事件,我自定義了一個(gè)WLabel類繼承自QLabel,重寫(xiě)了event方法。
bool WLabel::event(QEvent *e) { if(e->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = (QKeyEvent*)e; if(keyEvent->key() == Qt::Key_Tab) { qDebug()<<"press tab key"; return ture; } } return QLabel::event(e); }
事件會(huì)發(fā)送到WLabel類的event方法中,會(huì)打印出下面的結(jié)果。
3.事件過(guò)濾器
事件的傳送和處理流程的第一站是事件過(guò)濾器eventFilter(),某個(gè)對(duì)象A可以通過(guò)給另一個(gè)對(duì)象B安裝事件處理器,實(shí)現(xiàn)對(duì)對(duì)象B事件的監(jiān)聽(tīng)或者攔截功能。我們可以給A取名監(jiān)聽(tīng)器,B取名接收器。一個(gè)對(duì)象可以監(jiān)聽(tīng)多個(gè)對(duì)象,一個(gè)對(duì)象也可以被多個(gè)事件監(jiān)聽(tīng)。事件過(guò)濾器返回true則表示事件已經(jīng)處理完畢,否則傳遞給下一個(gè)監(jiān)聽(tīng)器或者接收器本身。
void QObject::installEventFilter(QObject *filterObj)
bool eventFilter(QObject *obj, QEvent *event);
Qt的事件過(guò)濾由以上兩個(gè)方法實(shí)現(xiàn),首先安裝一個(gè)事件過(guò)濾器,然后重寫(xiě)bool eventFilter(QObject *obj, QEvent *event)。
filterObj表示事件篩選器對(duì)象,它接收發(fā)送到此QObject對(duì)象的所有事件。篩選器可以停止事件,也可以將事件轉(zhuǎn)發(fā)給此QObject對(duì)象。事件過(guò)濾器filterObj通過(guò)它的eventFilter()函數(shù)接收事件。
eventFilter()有返回值。
- 如果返回true,表示事件過(guò)濾,不會(huì)發(fā)送到對(duì)象本身。
- 如果返回false,表示事件未過(guò)濾,會(huì)通過(guò)event()方法將事件分發(fā)到對(duì)象。
- 返回給基類進(jìn)行處理,例:return QObject::eventFilter(obj, event)。
Qt 事件過(guò)濾器(秒懂)_Mr.codeee的博客-CSDN博客
4.event方法
當(dāng)經(jīng)過(guò)事件過(guò)濾器后,未過(guò)濾掉的事件會(huì)進(jìn)入到event方法中,event()函數(shù)主要用于事件的分發(fā)。所以,如果你希望在事件分發(fā)之前做一些操作,就可以在派生類中重寫(xiě)這個(gè)event()函數(shù)。
例:實(shí)現(xiàn)一些鼠標(biāo)進(jìn)出的打印,鍵盤(pán)按鍵一些打印。
bool WLabel::event(QEvent *e) { if(e->type() == QEvent::Enter) { qDebug()<<"WLabel event :enter"; return true; } else if(e->type() == QEvent::Leave) { qDebug()<<"WLabel event :Leave"; return true; } else if(e->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = (QKeyEvent*)e; if(keyEvent->key() == Qt::Key_Tab) { qDebug()<<"press tab key"; return true; } } return QLabel::event(e); }
上述代碼中event如果事件e被識(shí)別并處理,則應(yīng)返回true,否則交給它的基類QLabel來(lái)處理。
5.鼠標(biāo)進(jìn)入事件
bool WLabel::event(QEvent *e) { if(e->type() == QEvent::Enter) { qDebug()<<"WLabel event :enter"; } return QLabel::event(e); }
上述代碼,
- 如果事件返回return QLabel::event(e),會(huì)將鼠標(biāo)進(jìn)入事件分發(fā)到 enterEvent(QEvent *event),會(huì)打印下面的語(yǔ)句。
- 如果打印語(yǔ)句后面 return ture,則不會(huì)將事件傳遞到enterEvent中。
void WLabel::enterEvent(QEvent *event) { qDebug()<<"WLabel enterEvent"; }
6.accept(),ignore()
在我們做UI界面時(shí),經(jīng)常會(huì)重寫(xiě)mousePressEvent,wheelEvent等函數(shù),根據(jù)不同情況要對(duì)事件event進(jìn)行特殊處理。
當(dāng)執(zhí)行event->accept()時(shí),意味著這次的事件已經(jīng)被“我”接受啦,只有我使用。
當(dāng)執(zhí)行event->ignore()時(shí),意味著這次的事件“我”不要接受他,函數(shù)執(zhí)行完event給我的父窗口,他會(huì)需要的。
差別也就是要不要傳遞給父窗口,accept不傳遞,ignore傳遞,注意是父窗口,不是基類。
到此這篇關(guān)于Qt 事件處理機(jī)制的深入理解的文章就介紹到這了,更多相關(guān)Qt 事件處理 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
VC中CDC、HDC、pDC區(qū)別與聯(lián)系及相互轉(zhuǎn)換
這篇文章主要介紹了VC中CDC、HDC、pDC區(qū)別與聯(lián)系及相互轉(zhuǎn)換的方法,非常的詳細(xì),有需要的小伙伴可以參考下,希望對(duì)大家學(xué)習(xí)VC能夠有所幫助。2015-11-11C++詳解如何通過(guò)模板實(shí)現(xiàn)元素的反序
這篇文章主要介紹了C++中模板(Template)實(shí)現(xiàn)元素的反序,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06C語(yǔ)言的常量,字符串,轉(zhuǎn)義字符,注釋你都了解嗎
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言的常量,字符串,轉(zhuǎn)義字符,注釋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-02-02c語(yǔ)言中十進(jìn)制轉(zhuǎn)二進(jìn)制顯示小工具的實(shí)現(xiàn)代碼
本篇文章是對(duì)c語(yǔ)言中十進(jìn)制轉(zhuǎn)二進(jìn)制顯示小工具的實(shí)現(xiàn)代碼進(jìn)行了詳細(xì)的分析的介紹,需要的朋友參考下2013-05-05C++使用cuBLAS加速矩陣乘法運(yùn)算的實(shí)現(xiàn)代碼
這篇文章主要介紹了C++使用cuBLAS加速矩陣乘法運(yùn)算,將cuBLAS庫(kù)的乘法運(yùn)算進(jìn)行了封裝,方便了算法調(diào)用,具體實(shí)現(xiàn)代碼跟隨小編一起看看吧2021-09-09Matlab控制電腦攝像實(shí)現(xiàn)實(shí)時(shí)人臉檢測(cè)和識(shí)別詳解
人臉識(shí)別過(guò)程主要由四個(gè)階段組成:人臉檢測(cè)、圖像預(yù)處理、面部特征提取和特征識(shí)別。這篇文章主要介紹了如何使用MATLAB控制筆記本電腦的攝像頭,并進(jìn)行實(shí)時(shí)人臉檢測(cè)和識(shí)別,需要的可以參考一下2022-10-10