QT事件傳遞與事件過濾器

2021-06-28 23:58:36 字數 4093 閱讀 4903

**:

qt事件的型別很多, 常見的qt的事件如下:

鍵盤事件: 按鍵按下和鬆開.

滑鼠事件: 滑鼠移動,滑鼠按鍵的按下和鬆開.

拖放事件: 用滑鼠進行拖放.

滾輪事件: 滑鼠滾輪滾動.

繪屏事件: 重繪螢幕的某些部分.

定時事件: 定時器到時.

焦點事件: 鍵盤焦點移動.

進入和離開事件: 滑鼠移入widget之內,或是移出.

移動事件: widget的位置改變.

大小改變事件: widget的大小改變.

顯示和隱藏事件: widget顯示和隱藏.

視窗事件: 視窗是否為當前視窗.

還有一些非常見的qt事件,比如socket事件,剪貼簿事件,字型改變,布局改變等等.

qt的事件和qt中的signal不一樣. 後者通常用來"使用"widget, 而前者用來"實現" widget. 比如乙個按鈕, 我們使用這個按鈕的時候, 我們只關心他clicked()的signal, 至於這個按鈕如何接收處理滑鼠事件,再發射這個訊號,我們是不用關心的. 但是如果我們要過載乙個按鈕的時候,我們就要面對event了. 比如我們可以改變它的行為,在滑鼠按鍵按下的時候(mouse press event) 就觸發clicked()的signal而不是通常在釋放的( mouse release event)時候.

事件的產生

一種是系統產生的;通常是window system把從系統得到的訊息,比如滑鼠按鍵,鍵盤按鍵等, 放入系統的訊息佇列中. qt事件迴圈的時候讀取這些事件,轉化為qevent,再依次處理.

事件的排程

兩種排程方式,一種是同步的, 一種是非同步.

while( !postedevents )

while( !qwsevnts )

while( !postedevents )

先處理qt事件佇列中的事件, 直至為空. 再處理系統訊息佇列中的訊息, 直至為空, 在處理系統訊息的時候會產生新的qt事件, 需要對其再次進行處理.

qt中事件處理的順序

4.經過了前面兩級過濾後,如果事件還沒被處理(前面函式的返回值為false),那麼就會進入接收者的event()函式,你可以裡面根據事件的不同型別盡情處理。

5.預設event()函式根據事件型別會呼叫不同的事件處理函式,類似mouseevent(),keyevent()去分別處理他們。

事件的派發和處理

首先說明qt中事件過濾器的概念. 事件過濾器是qt中乙個獨特的事件處理機制, 功能強大而且使用起來靈活方便. 通過它, 可以讓乙個物件偵聽攔截另外乙個物件的事件. 事件過濾器是這樣實現的: 在所有qt物件的基類: qobject中有乙個型別為qobjectlist的成員變數,名字為eventfilters,當某個qobjec (qobja)給另乙個qobject (qobjb)安裝了事件過濾器之後, qobjb會把qobja的指標儲存在eventfilters中. 在qobjb處理事件之前,會先去檢查eventfilters列表, 如果非空, 就先呼叫列表中物件的eventfilter()函式. 乙個物件可以給多個物件安裝過濾器. 同樣, 乙個物件能同時被安裝多個過濾器, 在事件到達之後, 這些過濾器以安裝次序的反序被呼叫. 事件過濾器函式( eventfilter() ) 返回值是bool型, 如果返回true, 則表示該事件已經被處理完畢, qt將直接返回, 進行下一事件的處理; 如果返回false, 事件將接著被送往剩下的事件過濾器或是目標物件進行處理.

同樣, 在reciver::event()中, 先檢查有無事件過濾器安裝在reciever上. 若有, 則呼叫之. 接下來,根據qevent的型別, 呼叫相應的特定事件處理函式. 一些常見的事件都有特定事件處理函式, 比如:mousepressevent(), focusoutevent(),  resizeevent(), paintevent(), resizeevent()等等. 在實際應用中, 經常需要過載這些特定事件處理函式在處理事件. 但對於那些不常見的事件, 是沒有相對應的特定事件處理函式的. 如果要處理這些事件, 就需要使用別的辦法, 比如過載event() 函式, 或是安裝事件過濾器.

事件的**

對於某些類別的事件, 如果在整個事件的派發過程結束後還沒有被處理, 那麼這個事件將會向上**給它的父widget, 直到最頂層視窗. 如圖所示, 事件最先傳送給qcheckbox, 如果qcheckbox沒有處理, 那麼由qgroupbox接著處理, 如果qgroupbox沒有處理, 再送到qdialog, 因為qdialog已經是最頂層widget, 所以如果qdialog不處理, qevent將停止**.

實際應用

1.過載特定事件處理函式

最常見的事件處理辦法就是過載象mousepressevent(), keypressevent(), paintevent() 這樣的特定事件處理函式. 以按鍵事件為例, 乙個典型的處理函式如下:

void imageview::keypressevent(qkeyevent * event)

switch (event->key())

2.過載event()函式

通過過載event()函式,我們可以在事件被特定的事件處理函式處理之前(象keypressevent())處理它. 比如, 當我們想改變tab鍵的預設動作時,一般要過載這個函式. 在處理一些不常見的事件(比如:layoutdirectionchange)時,evnet()也很有用,因為這些函式沒有相應的特定事件處理函式. 當我們過載event()函式時, 需要呼叫父類的event()函式來處理我們不需要處理或是不清楚如何處理的事件.

下面這個例子演示了如何過載event()函式, 改變tab鍵的預設動作: (預設的是鍵盤焦點移動到下乙個控制項上. )

bool codeeditor::event(qevent * event)

if (event->type() == qevent::keypress) {

qkeyevent *keyevent = (qkeyevent *) event;

if (keyevent->key() == key_tab) {

insertatcurrentposition('\t');

return true;

return qwidget::event(event);

3.在qt物件上安裝事件過濾器

安裝事件過濾器有兩個步驟: (假設要用a來監視過濾b的事件)

首先呼叫b的installeventfilter( const qoject *obj ), 以a的指標作為引數. 這樣所有發往b的事件都將先由a的eventfilter()處理.

然後, a要過載qobject::eventfilter()函式, 在eventfilter() 中書寫對事件進行處理的**.

用這種方法改寫上面的例子: (假設我們將codeeditor 放在mainwidget中)

mainwidget::mainwidget()

codeeditor * ce = new codeeditor( this, 「code editor」);

ce->installeventfilter( this );

bool mainwidget::eventfilter( qoject * target , qevent * event )

if( target == ce ){

if( event->type() == qevent::keypress ) {

qkeyevent *ke = (qkeyevent *) event;

if( ke->key() == key_tab ){

ce->insertatcurrentposition('\t');

return true;

return false;

4.經過了前面兩級過濾後,如果事件還沒被處理(前面函式的返回值為false),那麼就會進入接收者的event()函式,你可以裡面根據事件的不同型別盡情處理。

5.預設event()函式根據事件型別會呼叫不同的事件處理函式,類似mouseevent(),keyevent()去分別處理他們。

Qt 事件過濾器

qt 事件模型乙個真正強大的特色是乙個qobject的例項能夠管理另乙個qobject 例項的事件。乙個事件過濾器的安裝需要下面2個步驟 1 呼叫installeventfilter 註冊需要管理的物件。2 在eventfilter 裡處理需要管理的物件的事件。偽 如下 pfilterlineedi...

Qt 事件過濾器

目標部件有事件產生後,首先會傳遞給監視物件 事件過濾器 進行處理而不是該事件對應的事件處理器。所以說我們可以截獲事件進行處理。監視物件截獲目標物件的事件後就會呼叫自己的eventfilter 函式處理這些事件。bool qobject eventfilter qobject object,qeven...

Qt事件過濾器

昨天發了blog之後,提供一種不用子類化的方式來實現左鍵雙擊,就是使用qobject提供的事件過濾器來實現對其他物件的事件進行響應。這裡先安裝對應物件的事件過濾器,installeventfilter this 這樣只要該物件產生事件,就會先執行本物件的eventfilter 函式,在該函式裡先判斷...