事件過濾器


Qt 將事件封裝為QEvent實例之後,會呼叫QObject的event()方法並將QEvent實例傳送給它,在某些情況下,您希望物件在執行event ()處理事件之前,先對一些事件進行處理或過濾,然後再決定是否呼叫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);
....

您也可以將事件過濾器安裝在QApplication,在任何的事件發生後呼叫每個物件的event()方法之 前,會先經過事件過濾器,這給您更多控制應用程式事件的能力。

Qt 的事件迴圈與sendEvent()方法會呼叫QCoreApplication(QApplication的父類別)的notify()以分派事件,如果您想要完全控制Qt應用程式的事件,則可以重新定義 notify()方法

到這邊,可以看出Qt事件處理的五個層次:重新定義事件處理者、重新定義event()方法、為個別物件安裝事件過濾器、為QApplication安裝 事件過濾器,重新定義QCoreApplication的notify()方法。