程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Qt學習之路(22): 事件過濾器

Qt學習之路(22): 事件過濾器

編輯:關於C語言

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

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

virtual bool QObject::eventFilter ( QObject * watched, QEvent * event )
如果watched對象安裝了事件過濾器,這個函數會被調用並進行事件過濾,然後才輪到組件進行事件處理。在重寫這個函數時,如果你需要過濾掉某個事件,例如停止對這個事件的響應,需要返回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建立了一個事件過濾器。為了過濾某個組件上的事件,首先需要判斷這個對象是哪個組件,然後判斷這個事件的類型。例如,我不想讓textEdit組件處理鍵盤事件,於是就首先找到這個組件,如果這個事件是鍵盤事件,則直接返回true,也就是過濾掉了這個事件,其他事件還是要繼續處理,所以返回false。對於其他組件,我們並不保證是不是還有過濾器,於是最保險的辦法是調用父類的函數。

在創建了過濾器之後,下面要做的是安裝這個過濾器。安裝過濾器需要調用installEventFilter()函數。這個函數的簽名如下:

void QObject::installEventFilter ( QObject * filterObj )
這個函數是QObject的一個函數,因此可以安裝到任何QObject的子類,並不僅僅是UI組件。這個函數接收一個QObject對象,調用了這個函數安裝事件過濾器的組件會調用filterObj定義的eventFilter()函數。例如,textField.installEventFilter(obj),則如果有事件發送到textField組件是,會先調用obj->eventFilter()函數,然後才會調用textField.event()。

當然,你也可以把事件過濾器安裝到QApplication上面,這樣就可以過濾所有的事件,已獲得更大的控制權。不過,這樣做的後果就是會降低事件分發的效率。

如果一個組件安裝了多個過濾器,則最後一個安裝的會最先調用,類似於堆棧的行為。

注意,如果你在事件過濾器中delete了某個接收組件,務必將返回值設為true。否則,Qt還是會將事件分發給這個接收組件,從而導致程序崩潰。

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

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

本文出自 “豆子空間” 博客,請務必保留此出處http://devbean.blog.51cto.com/448512/231861

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved