在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ C/ 事件過濾器
Qt 容器和算法拾遺
自定義 model 之一
反走樣
Hello, world!
Qt 容器類之關(guān)聯(lián)存儲(chǔ)容器
QStringListModel
拖放技術(shù)之一
狀態(tài)欄
QTreeWidget
拖放技術(shù)之二
通用算法
event()
Qt 學(xué)習(xí)之路(18): Qt 標(biāo)準(zhǔn)對(duì)話框之 QInputDialog
Qt 容器類之遍歷器和隱式數(shù)據(jù)共享
QListWidget
Meta-Object 系統(tǒng)
事件接收與忽略
Qt 學(xué)習(xí)之路(tip): parent 參數(shù)
Qt 標(biāo)準(zhǔn)對(duì)話框之 QColorDialog
QPainter(續(xù))
國際化(下)
漸變填充
自定義委托
創(chuàng)建 shared library
model-view 架構(gòu)
Graphics View Framework
自定義拖放數(shù)據(jù)對(duì)象
QSortFilterProxyModel
國際化(上)
組件布局
自定義 Model 之三
事件過濾器
QDirModel
Hello, world!(續(xù))
Qt 標(biāo)準(zhǔn)對(duì)話框之 QFileDialog
自定義 model 之二
深入了解信號(hào)槽
坐標(biāo)變換
剪貼板操作
QTableWidget
QByteArray 和 QVariant
創(chuàng)建一個(gè)對(duì)話框(下)
Qt 學(xué)習(xí)之路(32): 一個(gè)簡(jiǎn)易畫板的實(shí)現(xiàn)(Graphics View)
文本文件讀寫
自定義事件
編寫跨平臺(tái)的程序
MainWindow
初探信號(hào)槽
Qt 學(xué)習(xí)之路(17): Qt 標(biāo)準(zhǔn)對(duì)話框之 QMessageBox
繪圖設(shè)備
菜單和工具條(續(xù))
二進(jìn)制文件讀寫
QString
事件(event)
菜單和工具條
QPainter
Qt 容器類之順序存儲(chǔ)容器
進(jìn)程間交互
API 文檔的使用
創(chuàng)建一個(gè)對(duì)話框(上)
一個(gè)簡(jiǎn)易畫板的實(shí)現(xiàn)(QWidget)

事件過濾器

Qt 創(chuàng)建了 QEvent 事件對(duì)象之后,會(huì)調(diào)用 QObject 的 event()函數(shù)做事件的分發(fā)。有時(shí)候,你可能需要在調(diào)用 event()函數(shù)之前做一些另外的操作,比如,對(duì)話框上某些組件可能并不需要響應(yīng)回車按下的事件,此時(shí),你就需要重新定義組件的 event()函數(shù)。如果組件很多,就需要重寫很多次 event()函數(shù),這顯然沒有效率。為此,你可以使用一個(gè)事件過濾器,來判斷是否需要調(diào)用 event()函數(shù)。

QOjbect 有一個(gè) eventFilter()函數(shù),用于建立事件過濾器。這個(gè)函數(shù)的簽名如下:

virtual bool QObject::eventFilter ( QObject * watched, QEvent * event )

如果 watched 對(duì)象安裝了事件過濾器,這個(gè)函數(shù)會(huì)被調(diào)用并進(jìn)行事件過濾,然后才輪到組件進(jìn)行事件處理。在重寫這個(gè)函數(shù)時(shí),如果你需要過濾掉某個(gè)事件,例如停止對(duì)這個(gè)事件的響應(yīng),需要返回 true。

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
 {
         if (obj == textEdit) {
                 if (event->type() == QEvent::KeyPress) {
                         QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
                         qDebug() << "Ate key press" << keyEvent->key();
                         return true;
                 } else {
                         return false;
                 }
         } else {
                 // pass the event on to the parent class
                 return QMainWindow::eventFilter(obj, event);
         }
 }

上面的例子中為 MainWindow 建立了一個(gè)事件過濾器。為了過濾某個(gè)組件上的事件,首先需要判斷這個(gè)對(duì)象是哪個(gè)組件,然后判斷這個(gè)事件的類型。例如,我不想讓 textEdit 組件處理鍵盤事件,于是就首先找到這個(gè)組件,如果這個(gè)事件是鍵盤事件,則直接返回 true,也就是過濾掉了這個(gè)事件,其他事件還是要繼續(xù)處理,所以返回 false。對(duì)于其他組件,我們并不保證是不是還有過濾器,于是最保險(xiǎn)的辦法是調(diào)用父類的函數(shù)。

在創(chuàng)建了過濾器之后,下面要做的是安裝這個(gè)過濾器。安裝過濾器需要調(diào)用 installEventFilter()函數(shù)。這個(gè)函數(shù)的簽名如下:

void QObject::installEventFilter ( QObject * filterObj )

這個(gè)函數(shù)是 QObject 的一個(gè)函數(shù),因此可以安裝到任何 QObject 的子類,并不僅僅是 UI 組件。這個(gè)函數(shù)接收一個(gè) QObject 對(duì)象,調(diào)用了這個(gè)函數(shù)安裝事件過濾器的組件會(huì)調(diào)用 filterObj 定義的eventFilter()函數(shù)。例如,textField.installEventFilter(obj),則如果有事件發(fā)送到textField 組件是,會(huì)先調(diào)用 obj->eventFilter()函數(shù),然后才會(huì)調(diào)用 textField.event()。

當(dāng)然,你也可以把事件過濾器安裝到 QApplication 上面,這樣就可以過濾所有的事件,已獲得更大的控制權(quán)。不過,這樣做的后果就是會(huì)降低事件分發(fā)的效率。

如果一個(gè)組件安裝了多個(gè)過濾器,則最后一個(gè)安裝的會(huì)最先調(diào)用,類似于堆棧的行為。

注意,如果你在事件過濾器中 delete 了某個(gè)接收組件,務(wù)必將返回值設(shè)為 true。否則,Qt 還是會(huì)將事件分發(fā)給這個(gè)接收組件,從而導(dǎo)致程序崩潰。

事件過濾器和被安裝的組件必須在同一線程,否則,過濾器不起作用。另外,如果在 install 之后,這兩個(gè)組件到了不同的線程,那么,只有等到二者重新回到同一線程的時(shí)候過濾器才會(huì)有效。

事件的調(diào)用最終都會(huì)調(diào)用 QCoreApplication 的 notify()函數(shù),因此,最大的控制權(quán)實(shí)際上是重寫QCoreApplication 的 notify()函數(shù)。由此可以看出,Qt 的事件處理實(shí)際上是分層五個(gè)層次:重定義事件處理函數(shù),重定義 event()函數(shù),為單個(gè)組件安裝事件過濾器,為 QApplication 安裝事件過濾器,重定義 QCoreApplication 的 notify()函數(shù)。這幾個(gè)層次的控制權(quán)是逐層增大的。

本文出自 “豆子空間” 博客,請(qǐng)務(wù)必保留此出處 http://devbean.blog.51cto.com/448512/194031