1. 程式人生 > >Qt Event Dispatcher學習

Qt Event Dispatcher學習

距離上次整理Qt事件系統已經過了14個月了。重新理理思緒:

Qt中的事件大致可分為3類:

Spontaneous events

從系統得到的訊息:滑鼠按鍵、鍵盤按鍵、定時器事件等。轉化為QEvent後被Qt事件系統依次處理

Posted events

由Qt或應用程式直接生成,放入Qt訊息佇列
QCoreApplication::postEvent()

Sent events

由Qt或應用程式產生,不放入佇列直接被派發和處理
QCoreApplication::sendEvent()

本文中,先簡單看一下後兩種,然後重點看看第一種。

Sent events

比如,傳送按鍵"X"的事件到 mainWin 視窗。

QKeyEvent event(QEvent::KeyPress, Qt::Key_X, Qt::NoModifier, "X", 0
);
QApplication::sendEvent(mainWin, &event);

如果沒有過濾器的話,這其實就是直接呼叫 mainWin 的 keyPressEvent()函式。


這個東西不涉及事件佇列、事件迴圈等等東西。但是事件過濾在這個過程中正常起作用。而且除過濾器外,下面三個函式在派生類中都可以被覆蓋(以處理這個事件):

  • QApplication::notify()
  • QWidget::event()
  • QWidget::keyPressEvent()

Posted events

比如,同樣是傳送按鍵"X"的事件到 mainWin 視窗,我們可以使用postEvent()。

QApplication::postEvent(mainWin, new QKeyEvent(QEvent::KeyPress, Qt::Key_X, Qt::NoModifier, "X", 0
));

這會將該事件放入Qt自己的事件佇列中,事件迴圈QEventLoop空閒時會判斷該佇列是否為空。最終使用 sendEvent() 依次派發事件佇列中的這些事件。


也可以手動使用

  • QCoreApplication::sendPostedEvents()

清空當前執行緒事件佇列(即派發佇列中的事件)

注意:每一個執行緒有一個事件佇列。

Spontaneous events

系統底層事件是通過 QAbstractEventDispatcher 整合進Qt的事件迴圈的。

Event dispatcher接受視窗系統以及其他源中的事件。它對事件的傳遞提供了一種精細控制的能力。

QAbstractEventDispatcher

  • QEventDispatcherUNIX
    • QEventDispatcherX11
    • QEventDispatcherQWS
    • QEventDispatcherQPA
  • QEventDispatcherGlib
    • QGuiEventDispatcherGlib
    • QWSEventDispatcherGlib
  • QEventDispatcherWin32
    • QGuiEventDispatcherWin32
  • QEventDispatcherMac
  • ...

這堆東西還挺多,不過下面三個屬於QtCore模組

QEventDispatcherGlib

使用glib事件迴圈,有助於和Gtk的整合

QEventDispatcherUNIX

預設的glib不可用時,就用這個嘍

QEventDispatcherWin32

Qt 建立一個帶回調函式的隱藏視窗來處理事件。

我們能看的到的就是,它們提供

  • Timer
  • SockerNotifer

的註冊、反註冊功能。並將系統底層對應事件轉換成Qt事件。


其他的屬於QtGui模組。就是和視窗系統(重繪、移動等等事件)以及鍵鼠事件有關了。

參考