Qt 事件機制 學習

2021-08-28 23:51:43 字數 4413 閱讀 8588

qt程式是事件驅動的, 程式的每個動作都是由幕後某個事件所觸發.。

qt事件的發生和處理成為程式執行的主線,存在於程式整個生命週期。

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

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

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

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

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

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

定時事件: 定時器到時.

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

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

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

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

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

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

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

交流會圍繞以下三個問題展開:

一、什麼是事件?

二、事件是怎樣被處理的?

三、事件與訊號的區別?

一、什麼是事件?

事件:某個「動作」的完成後,需讓某個物件知道而傳送的訊息。(個人觀點)

解釋:此時的「動作」並非通常意義所指的動作,而是廣義的「動作」,是主動和被動的總和。

例:兩個窗體a和b,當a為最小化狀態時,我們使它最大化,這就會讓a主動產生乙個重繪事件;當a和b非最小化狀態,且b位於a窗體之上時,我們讓b最小化,那麼剛才被b遮擋的a窗體就會被動地產生乙個重繪事件。

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

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

二、事件是怎樣被處理的?

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

while( !postedevents )

while( !qwsevnts )

while( !postedevents )

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

(二) 事件的派發和處理

首先說明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() 函式, 或是安裝事件過濾器.

事件派發和處理的流程圖如下:

(三) 事件的**

(四)實際運用

根據對qt事件機制的分析, 我們可以得到5種級別的事件過濾,處理辦法. 以功能從弱到強, 排列如下:

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

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

void imageview::keypressevent(qkeyevent *event)

switch (event->key()) {

case key_plus:

zoomin();

break;

case key_minus:

zoomout();

break;

case key_left:

default:

qwidget::keypressevent(event);

(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;

三、事件與訊號的區別?

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

訊號通過事件實現,事件可以過濾,事件更底層,事件是基礎,訊號是擴充套件。

qt 事件機制

什麼是自發事件?哪些型別的事件可以被propagated 或compressed?posting and sending 事件之間有何不同?什麼時候應該呼叫 accept 或是ignore 如果這些問題你還不是很了解,那麼繼續看下去。事件起源 定製事件型別 到現在為至,我們所說的內容不僅僅適用於ke...

QT事件機制

什麼是自發事件?哪些型別的事件可以被propagated 或compressed?posting and sending 事件之間有何不同?什麼時候應該呼叫 accept 或是ignore 如果這些問題你還不是很了解,那麼繼續看下去。事件起源 到現在為至,我們所說的內容不僅僅適用於key事件,也適用...

qt事件機制

coffeegg qt事件機制 學習了一段時間的qt之後,發現qt的事件機制和其他語言的機制有些不同。qt除了能夠 通過訊號和槽機制來實現一些action動作之外,還可以用物件所帶的事件,或者使用者自 定義的事件來實現物件的一些行為處理。現在,我們從頭開始講解。到底什麼是事件呢?事件起源 基於事件如...