1. 程式人生 > >installEventFilter可以安裝到任何QObject的子類,並不僅僅是UI組件。事件過濾器和安裝過濾器的組件必須在同一線程,在它們分屬在不同線程時,事件過濾器也是不起作用的

installEventFilter可以安裝到任何QObject的子類,並不僅僅是UI組件。事件過濾器和安裝過濾器的組件必須在同一線程,在它們分屬在不同線程時,事件過濾器也是不起作用的

聲明 其它 -- crash t對象 對象傳遞 receiver 有效 每一個

Qt的事件知識點:
①事件對象創建完畢後,Qt 將這個事件對象傳遞給 QObject 的 event() 函數。event() 函數並不直接處理事件,而是將這些事件對象按照它們不同的類型,分發給不同的事件處理器(event handler)。

②event() 函數主要用於事件的分發。

③事件過濾例子:

解釋這個例子之前先看:bool eventFilter(QObject*obj,QEvent*event); [virtual]
註意: eventFilter 函數返回 bool 值,

即, 如果你要自己處理事件, 並且“吞掉”事件,阻止父類對事件的繼續處理, 就返回 true; 如果需要父類也處理這一事件,返回 false。通俗點說就是:

它會檢查接收到的事件。如果這個事件是我們感興趣的類型,就進行我們自己的處理;如果不是,就繼續轉發。

這個函數返回一個 bool 類型,如果你想將參數 event過濾出來,比如,不想讓它繼續轉發,就返回 true,否則返回 false。事件過濾器的調用時間是目標對象(也就是參數裏面的 watched對象)接收到事件對象之前。也就是說,如果你在事件過濾器中停止了某個事件,那麽,watched對象以及以後所有的事件過濾器根本不會知道這麽一個事件。

那麽上面的例子的意思就是:

MainWindow是我們定義的一個類,這個類裏面會定義許多不同的組件,比如texEdit,我們就是使用MainWindow的eventFilter()函數對它上面的組件進行過濾事件。我們重寫了它的 eventFilter()函數。為了過濾特定組件上的事件,首先需要判斷這個對象是不是我們感興趣的組件,然後判斷這個事件的類型。在上面的代碼中,我們不想讓textEdit組件處理鍵盤按下的事件。所以,首先我們找到這個組件,如果這個事件是鍵盤事件,則直接返回 true,也就是過濾掉了這個事件,其他事件還是要繼續處理,所以返回 false。對於其它的組件,我們並不保證是不是還有過濾器,於是最保險的辦法是調用父類的函數。

當返回true是textEdit組件內部是不能用鍵盤輸入字符的,但是可以粘貼,這說明是被過濾掉了,但是返回false是就可以用鍵盤輸入字符。

④voidQObject::installEventFilter(QObject* filterObj )

這個函數是QObject的一個函數,因此可以安裝到任何QObject的子類,並不僅僅是UI組件。這個函數接收一個QObject對象,調用了這個函數安裝事件過濾器的組件會調用filterObj定義的eventFilter()函數。例如,textField.installEventFilter(obj),則如果有事件發送到textField組件是,會先調用obj->eventFilter()函數,然後才會調用textField.event()。

我們可以向一個對象上面安裝多個事件處理器,只要調用多次 installEventFilter()函數。如果一個對象存在多個事件過濾器,那麽,最後一個安裝的會第一個執行,也就是後進先執行的順序。一般這個函數的調用時在構造函數裏面:

⑤如果你在事件過濾器中 delete了某個接收組件,務必將函數返回值設為 true。否則,Qt還是會將事件分發給這個接收組件,從而導致程序崩潰。

事件過濾器和被安裝過濾器的組件必須在同一線程,否則,過濾器將不起作用。另外,如果在安裝過濾器之後,這兩個組件到了不同的線程,那麽,只有等到二者重新回到同一線程的時候過濾器才會有效。(大牛解釋是:事件過濾器和安裝過濾器的組件必須在同一線程。Qt 裏面,對象創建之後,可以使用 moveToThread() 函數將一個對象移動到另外的線程。在這種情形下(當然,事件過濾器必須在同一線程時才能被正確安裝,這是第一句話說明的),在它們分屬在不同線程時,事件過濾器也是不起作用的,只用當它們重新回到同一線程(使用 moveToThread() 或者是線程自然結束)時,過濾器才能重新工作。)

⑥如果使用 installEventFilter() 函數給一個對象安裝事件過濾器,那麽該事件過濾器只對該對象有效,只有這個對象的事件需要先傳遞給事件過濾器的 eventFilter() 函數進行過濾,其它對象不受影響。

⑦如果給 QApplication 對象安裝事件過濾器,那麽該過濾器對程序中的每一個對象都有效,任何對象的事件都是先傳給 eventFilter() 函數而且第一個獲得該事件。

⑧事件的分發既可以是同步的,又可以是異步的,而函數的調用或者說是槽的回調總是同步的。事件的另外一個好處是,它可以使用過濾器。

void QObject::installEventFilter(QObject * filterObj)
Installs an event filter filterObj on this object. For example:

An event filter is an object that receives all events that are sent to this object. The filter can either stop the event or forward it to this object. The event filter filterObj receives events via its eventFilter() function. TheeventFilter() function must return true if the event should be filtered, (i.e. stopped); otherwise it must return false.

If multiple event filters are installed on a single object, the filter that was installed last is activated first.

Here‘s a KeyPressEater class that eats the key presses of its monitored objects:

And here‘s how to install it on two widgets:

The QShortcut class, for example, uses this technique to intercept shortcut key presses.

Warning: If you delete the receiver object in your eventFilter() function, be sure to return true. If you return false, Qt sends the event to the deleted object and the program will crash.

Note that the filtering object must be in the same thread as this object. IffilterObj is in a different thread, this function does nothing. If either filterObjor this object are moved to a different thread after calling this function, the event filter will not be called until both objects have the same thread affinity again (it is not removed).
---------------------
作者:helmsgao
來源:CSDN
原文:https://blog.csdn.net/love_gaohz/article/details/10496631
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

installEventFilter可以安裝到任何QObject的子類,並不僅僅是UI組件。事件過濾器和安裝過濾器的組件必須在同一線程,在它們分屬在不同線程時,事件過濾器也是不起作用的