1. 程式人生 > >Qt中的事件處理機制(event)

Qt中的事件處理機制(event)

Qt事件也就是Qt程式中出現的一系列“事情”,包括對使用者操作做出反應時發出的滑鼠或鍵盤事件等;以及系統內部自動發出的定時器事件等。總之,出現了這些事件後就需要對這些事件進行處理,處理的方法便是“事件處理機制”。

圖1 Qt事件產生

以使用者操作事件為例,其事件處理過程如下圖。

圖2 Qt事件處理過程

上述過程通過作業系統Qt平臺的處理,將使用者具體的一個操作指令(如滑鼠點選)轉化為一個Qt事件(即一個QEvent物件),這個Qt事件產生後,需要進行事件分發,所以就立刻被傳給了函式virtual bool event (QEvent *e),

這個QObject中的虛擬函式在其子類QWidget中被重新實現了,event()根據事件型別呼叫不同的事件處理函式。在事件處理函式中傳送QT預定義的訊號,最終呼叫訊號關聯的槽函式。(任意的QObject物件都具備事件處理的能力

而Qt平臺(Qt程式)建立Qt事件的過程是這樣的,程式的main()函式都會建立一個QApplication類物件,並呼叫其exec()函式,這個函式會使Qt應用程式進入事件迴圈,監聽應用程式的事件。這樣就可以使應用程式在執行時候接受發生的各種事件,一旦有事件發生,Qt便會建立一個相應的QEvent子類物件的事件來表示,然後傳遞給相應的QObject的event()函式進行事件分發。

Qt事件類都是繼承於QEvent,其繼承關係如圖。

圖3 Qt事件類繼承關係

QWidget中的事件處理函式有很多,他們是protected virtual的,可以在他們的子類中重新實現,如keyPressEvent(QKeyEvent *event)、keyReleaseEvent(QKeyEvent *event)、mouseMoveEvent(QMouseEvent *event)、mousePressEvent(QMouseEvent *event)、mouseReleaseEvent(QMouseEvent *event)

等。

仔細來看,事件與訊號其實並無多大差別,從我們對其需求上來說,都只要能註冊事件或訊號響應函式,在事件或訊號產生時能夠被通知到即可。但有一項區別在於,事件處理函式的返回值是有意義的,我們要根據這個返回值來確定是否還要繼續事件的處理,比如在QT中,事件處理函式如果返回true,則這個事件處理已完成,QApplication會接著處理下一個事件,而如果返回false,那麼事件分派函式會繼續向上尋找下一個可以處理該事件的註冊方法。訊號處理函式的返回值對訊號分派器來說是無意義的。

    另外還有一個需要我們關注的問題是事件和訊號處理時的優先順序問題。在QT中,事件因為都是與視窗相關的,所以事件回撥時都是從當前視窗開始,一級一級向上派發,直到有一個視窗返回true,截斷了事件的處理為止。對於訊號的處理則比較簡單,預設是沒有順序的,如果需要明確的順序,可以在訊號註冊時顯示地指明槽的位置。

在QT中,事件使用了一個事件佇列來維護,如果事件的處理中又產生了新的事件,那麼新的事件會加入到佇列尾,直到當前事件處理完畢後, QApplication再去佇列頭取下一個事件來處理。而訊號的處理方式有些不同,訊號處理是立即回撥的,也就是一個訊號產生後,他上面所註冊的所有槽都會立即被回撥。這樣就會產生一個遞迴呼叫的問題,比如某個訊號處理器中又產生了一個訊號,會使得訊號的處理像一棵樹一樣的展開。