2010年9月14日 星期二

Qt4 學習筆記(七):Event Filter

  • Event Filter
Qt將事件封裝為QEvent實例之後,會呼叫QObject的event()方法並將QEvent實例傳送給它,在某些情況下,會希望物件在執行event()處理事件之前,先對一些事件進行處理或過濾,然後再決定是否呼叫event()方法,這個時候就可以使用事件過濾器。

舉例來說,對QWidget按鍵事件的Tab鍵處理而言,如果圖形介面中有很多的元件,每個圖型元件都要如當中的範例重新定義event()方法,顯然是非常沒有效率且沒什麼維護性的方法。

可以藉由自定義一個物件繼承QObject(或其子類別),重新定義它的eventFilter()方法,例如自定義了一個FilterObject,希望Tab鍵可以用來將焦點轉移至下一個子元件:
bool FilterObject::eventFilter(QObject *object, QEvent *event) {
    if(event->type() == QEvent::KeyPress) {
        QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
        if (keyEvent->key() == Qt::Key_Tab) {
            // 處理Tab鍵
            return true;
        }
    }
    return false;
}
eventFilter()的object參數表示事件發生的來源物件,eventFilter()若傳回false,則安裝該事件過濾器的物件之event()就會繼續執行,若傳回true,則安裝該事件過濾器的物件之event()方法就不會被執行,由此進行事件的攔截處理。

要為指定的物件安裝事件過濾器,可以使用物件的installEventFilter()方法,例如:
QLineEdit *nameEdit = new QLineEdit;
QLineEdit *addressEdit = new QLineEdit;
...
FilterObject filter = new FilterObject;
...
nameEdit->installEventFilter(filter);
addressEdit->installEventFilter(filter);
....

Notes:
  • 也可以將事件過濾器安裝在QApplication,在任何的事件發生後呼叫每個物件的event()方法之前,會先經過事件過濾器,這可提供更多控制應用程式事件的能力。
  • Qt的事件迴圈與sendEvent()方法會呼叫QCoreApplication(QApplication的父類別)的notify()以分派事件,如果想要完全控制Qt應用程式的事件,則可以重新定義notify()方法。
P.S.
由此可以看出Qt事件處理的五個層次:
  1. 重新定義事件處理者
  2. 重新定義event()方法
  3. 為個別物件安裝事件過濾器
  4. 為QApplication安裝事件過濾器
  5. 重新定義QCoreApplication的notify()方法

0 意見: