Qt 學習之路 2(21) 事件過濾器

2021-08-08 16:32:27 字數 3585 閱讀 9115

有時候,物件需要檢視、甚至要攔截傳送到另外物件的事件。例如,對話方塊可能想要攔截按鍵事件,不讓別的元件接收到;或者要修改回車鍵的預設處理。

通過前面的章節,我們已經知道,qt 建立了qevent事件物件之後,會呼叫qobjectevent()函式處理事件的分發。顯然,我們可以在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 函式之前做一些另外的操作,比如,對話方塊上某些元件可能...