? ? ? ? 事件和信號的區別在于,事件通常是由窗口系統或應用程序產生的,信號則是Qt定義或用戶自定義的。Qt為界面組件定義的信號往往通常是對事件的封裝,如QPushButton的clicked()信號可以看做對QEvent::MouseButtonRelease類事件的封裝。
? ? ? ? 在使用界面組件作為交互操作編程的時候,我們通常選擇合適的信號,為該信號編寫槽函數。但是Qt的界面組件只將少數事件進行封裝成了信號,對于某些事件可能缺少對應的信號,例如QLabel的信號中就沒有與雙擊鼠標對應的信號
? ? ? ? 在這種情況下我們可以從QLabel繼承定義一個新的標簽類,通過自定義信號和事件處理,使新的標簽類具有處理鼠標雙擊事件的信號。
? ? ? ? 函數event()的作用
? ? ? ? 應用程序派發給界面組件的事件首先會由其函數event()處理,如果函數event()不做任何處理,組件就會自動調用QWidget中與事件類型對應的默認事件處理函數,從QWidget派生的界面組件一般不需要重新實現函數event(),如果對某種事件進行處理,可以重新實現其對應的事件處理函數。
? ? ? ? QWidget類針對一些典型事件編寫了事件處理函數,但是某些類型的事件沒有對應的事件處理函數,例如,對于QEvent::HoverEnter和QEvent::HoverLeave類型的事件,QWidget類中就沒有對應的事件處理函數,這種情況下,如果要對QEvent::HoveEnter和QEvent::HoveLeave類型的事件進行處理,就需要自定義一個類,重新實現函數event(),判斷事件類型,針對QEvent::HoveEnter和QEvent::HoveLeave類型的事件進行對應的處理。
?注意,TMyLabel中的構造函數我是改變了其中參數的,因為使用創建C++類向導自動生成的TMyLabel的構造函數是沒有任何參數的,這樣是不對的,因為界面組件必須要有一個父容器組件
注意在構造函數中我們將TMyLabel的Qt::WA_Hover屬性設置為true(默認值是false)。這樣鼠標光標移入和移出才會分別產生QEvent::HoveEnter和QEvent::HoveLeave類型的事件。?
? ? ? ? 事件過濾器
? ? ? ? 一個界面組件如果要對事件進行處理,需要從父類繼承定義一個新類,在新類里編寫程序直接處理事件,或者將事件轉換成信號。
? ? ? ? 如果不想定義一個新的類,可以用事件過濾器對界面組件的事件進行處理。事件過濾器是QObject提供的一種處理事件的方法,它可以將一個對象的事件委托給另一個對象來監聽并處理。
? ? ? ? 事件過濾器工作原理
? ? ? ? QObject提供了一種處理事件的方法,事件過濾器。它可以將一個對象的事件委托給另一個對象來監視并處理。例如,一個窗口可以作為其他界面上的QLabel組件的事件過濾器,派發給QLabel組件的事件由窗口去處理,這樣,就不需要為了處理某種事件而新定義一個標簽類。
? ? ? ? 要實現事件過濾器功能,需要完成兩項操作。
? ? ? ? (1)被監視對象使用函數installEventFilter()將自己注冊給監視對象,監視對象就是事件過濾器。
? ? ? ? (2)監視對象重新實現eventFilter()函數,對監視到的事件進行處理。
???????installEventFilter()和eventFilter()都是QObject類定義的公有函數,函數installEventFilter()的原型定義如下:
? void QObject::installEventFilter(QObject* filterObj)
? ? ? ? 被監視的對象調用installEventFilter(),將對象filterObj設置為自己的事件過濾器。
? ? ? ? 函數eventFilter()的原型定義如下:
bool QObject::eventFilter(QObject* watched , QEvent* event)
? ? ? ? 作為事件過濾器的監視對象需要重新實現eventFilter(),參數watched 是被監視的對象,event是產生的事件。這個函數有一個返回值,如果返回true,事件就不會再傳播給其他對象,事件處理結束,如果返回false,事件會繼續傳播給事件接受者做進一步處理。
注意eventFilter()函數結尾不能直接返回true,如果返回true的話,事件過濾器攔截的事件不會繼續傳播給被監視對象,而在這個類的eventFilter()函數中,我們只處理了被監視對象的少數幾個事件件,例如QEvent::Paint類型的事件就沒有處理,程序運行時界面上根本就不顯示標簽的文字。
注意 QEvent::Enter和QEventLeave兩個類型的事件,它們與QEvent::HoverEnter和QEvent::HoverLeave類型的事件功能相似,只是使用Hover事件時,需要將組件的mouseTracking屬性設置為true,而使用QEvent::Enter和QEventLeave兩個類型的事件時無需設置這個屬性