有時候,物件需要檢視、甚至要攔截傳送到另外物件的事件。例如,對話方塊可能想要攔截按鍵事件,不讓別的元件接收到;或者要修改回車鍵的預設處理。
通過前面的章節,我們已經知道,qt 建立了qevent
事件物件之後,會呼叫qobject
的event()
函式處理事件的分發。顯然,我們可以在event()
函式中實現攔截的操作。由於event()
函式是 protected 的,因此,需要繼承已有類。如果元件很多,就需要重寫很多個event()
函式。這當然相當麻煩,更不用說重寫event()
函式還得小心一堆問題。好在 qt 提供了另外一種機制來達到這一目的:事件過濾器。
qobject
有乙個eventfilter()
函式,用於建立事件過濾器。這個函式的簽名如下:
1
virtual
bool
qobject
::eventfilter
(qobject *
watched
,qevent *
event);
這個函式正如其名字顯示的那樣,是乙個「事件過濾器」。所謂事件過濾器,可以理解成一種過濾**。想想做化學實驗時用到的過濾器,可以將雜質留到濾紙上,讓過濾後的液體溜走。事件過濾器也是如此:它會檢查接收到的事件。如果這個事件是我們感興趣的型別,就進行我們自己的處理;如果不是,就繼續**。這個函式返回乙個 bool 型別,如果你想將引數 event 過濾出來,比如,不想讓它繼續**,就返回 true,否則返回 false。事件過濾器的呼叫時間是目標物件(也就是引數裡面的watched
物件)接收到事件物件之前。也就是說,如果你在事件過濾器中停止了某個事件,那麼,watched
物件以及以後所有的事件過濾器根本不會知道這麼乙個事件。
我們來看一段簡單的**:
12
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class
mainwindow
:public
qmainwindow
; mainwindow
::mainwindow()
bool
mainwindow
::eventfilter
(qobject *
obj,
qevent *
event)
else
}else
} mainwindow
是我們定義的乙個類。我們重寫了它的eventfilter()
函式。為了過濾特定元件上的事件,首先需要判斷這個物件是不是我們感興趣的元件,然後判斷這個事件的型別。在上面的**中,我們不想讓textedit
元件處理鍵盤按下的事件。所以,首先我們找到這個元件,如果這個事件是鍵盤事件,則直接返回 true,也就是過濾掉了這個事件,其他事件還是要繼續處理,所以返回 false。對於其它的元件,我們並不保證是不是還有過濾器,於是最保險的辦法是呼叫父類的函式。
eventfilter()
函式相當於建立了過濾器,然後我們需要安裝這個過濾器。安裝過濾器需要呼叫qobject::installeventfilter()
函式。這個函式的簽名如下:
1
void
qobject
::installeventfilter
(qobject *
filterobj
)
這個函式接受乙個qobject *
型別的引數。記得剛剛我們說的,eventfilter()
函式是qobject
的乙個成員函式,因此,任意qobject
都可以作為事件過濾器(問題在於,如果你沒有重寫eventfilter()
函式,這個事件過濾器是沒有任何作用的,因為預設什麼都不會過濾)。已經存在的過濾器則可以通過qobject::removeeventfilter()
函式移除。
我們可以向乙個物件上面安裝多個事件處理器,只要呼叫多次installeventfilter()
函式。如果乙個物件存在多個事件過濾器,那麼,最後乙個安裝的會第乙個執行,也就是後進先執行的順序。
還記得我們前面的那個例子嗎?我們使用event()
函式處理了 tab 鍵:
12
3
4
5
6
7
8
9
10
11
bool
customwidget
::event
(qevent *e)
} return
qwidget
::event(e);}
現在,我們可以給出乙個使用事件過濾器的版本:
12
3
4
5
6
7
8
9
10
11
12
13
bool
filterobject
::eventfilter
(qobject *
object
,qevent *
event)
else
} return
false;
}注意,如果你在事件過濾器中 delete 了某個接收元件,務必將函式返回值設為 true。否則,qt 還是會將事件分發給這個接收元件,從而導致程式崩潰。
事件過濾器和被安裝過濾器的元件必須在同一執行緒,否則,過濾器將不起作用。另外,如果在安裝過濾器之後,這兩個元件到了不同的執行緒,那麼,只有等到二者重新回到同一執行緒的時候過濾器才會有效。
Qt學習之路 22 事件過濾器
qt建立了qevent事件物件之後,會呼叫qobject的event 函式做事件的分發。有時候,你可能需要在呼叫event 函式之前做一些另外的操作,比如,對話方塊上某些元件可能並不需要響應回車按下的事件,此時,你就需要重新定義元件的event 函式。如果元件很多,就需要重寫很多次event 函式,...
Qt學習之路 9 事件過濾器
text installeventfilter this bool mainwindow eventfilter qobject obj,qevent event return false 不過濾 return qmainwindow eventfilter obj,event 對於其他元件,不確定...
Qt學習之路 22 事件過濾器
2009 11 22 12 21 40 標籤 c 學習教程 qt教程qt 原始出處 作者資訊和本宣告。否則將追究法律責任。qt建立了qevent事件物件之後,會呼叫qobject的event 函式做事件的分發。有時候,你可能需要在呼叫event 函式之前做一些另外的操作,比如,對話方塊上某些元件可能...