Qt 事件过滤器
Qt 事件模型一個真正強大的特色是一個QObject的實例能夠管理另一個QObject 實例的事件。
一個事件過濾器的安裝需要下面2個步驟:
1、調用installEventFilter()注冊需要管理的對象。
2、在eventFilter() 里處理需要管理的對象的事件。
偽代碼如下:
pFilterLineEdit->installEventFilter(new EventFilter(this)); class EventFilter : public QObject { public:explicit EventFilter(QObject *parent = 0);~EventFilter();protected:virtual bool eventFilter(QObject *obj, QEvent *event); };EventFilter::EventFilter(QObject *parent): QObject(parent) {}EventFilter::~EventFilter() {}bool EventFilter::eventFilter(QObject *obj, QEvent *event) {QLineEdit *pLineEdit = qobject_cast<QLineEdit *>(obj);if (pLineEdit != NULL){switch (event->type()){case QEvent::MouseMove:case QEvent::MouseButtonDblClick:return true;case QEvent::KeyPress:{QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(event);if(pKeyEvent->matches(QKeySequence::SelectAll)|| pKeyEvent->matches(QKeySequence::Copy)|| pKeyEvent->matches(QKeySequence::Paste)){return true;}}}}return QObject::eventFilter(obj, event); }
注意,如果你在事件過濾器中delete了某個接收組件,務必將返回值設為true。否則,Qt還是會將事件分發給這個接收組件,從而導致程序崩潰。
事件過濾器和被安裝的組件必須在同一線程,否則,過濾器不起作用。另外,如果在install之后,這兩個組件到了不同的線程,那么,只有等到二者重新回到同一線程的時候過濾器才會有效。
Qt提供了5個級別來處理和過濾事件.
1. 我們可以重新實現特定的event handler.
??? 重新實現像mousePressEvent(), keyPressEvent()和paintEvent()這樣的event Handler是目前處理event最普通的方式.
2. 我們可以重新實現QObject::event().
??? 通過重新實現event(),我們可以在事件到達特定的event handler之前對它們作出處理. 這個方法主要是用來覆寫Tab鍵的缺省實現. 也可以用來處理不同發生的事件類型,對它們,就沒有特定的event handler. 當重新實現event()的時候,我們必須調用基類的event()來處理我們不顯式處理的情況.
3. 我們可以安裝一個event filter到一個單獨的QObject.
??? 一旦一個對象用installEventFilter注冊了, 發到目標對象的所有事件都會先發到監測對象的eventFilter(). 如果同一object安裝了多個event filter, filter會依次被激活, 從最近安裝的回到第一個.
4. 我們可以在QApplication對象上安裝event filter.
??? 一旦一個event filter被注冊到qApp(唯一的QApplication對象), 程序里發到每個對象的每個事件在發到其他event filter之前,都要首先發到eventFilter(). 這個方法對debugging非常有用. 也可以用來處理發到disable的widget上的事件, QApplication通常會丟棄它們.
5. 我們可以子類QApplication并重新實現notify().
??? Qt調用QApplication::notify()來發出事件. 在任何event filter得到之前, 重新實現這個函數是得到所有事件的唯一方法. event filter通常更有用, 因為可以有任意數目且同時存在的event filter, 但是只有一個notify()函數.
???
許多事件類型,包括鼠標和按鍵事件, 可以被傳播. 如果一個事件沒有在傳到目標對象的過程中被處理,或者被目標對象本身處理, 整個事件處理過程會重復, 不過, 這次, 目標對象的parent作為新的目標對象. 從parent到parent,這樣繼續下去,知道事件被處理了,或者到達了頂層的對象.
總結
- 上一篇: spring boot 表单的实体提交错
- 下一篇: 文本框input:text