在 Qt 事件機制系列的最後一篇中,我們將深入探討自定義事件的設計與實作。前幾篇已經介紹了 Qt 事件系統的核心架構、事件分發流程以及事件過濾器的使用,現在我們要解決一個關鍵問題:如何創建屬於自己的事件類型?
Qt 的信號與槽機制雖然強大,但本質上是同步調用。而事件系統提供了同步與異步兩種分發方式,這在多線程程式設計中極具價值。此外,事件還支援事件過濾器,允許在事件到達目標物件前進行攔截與處理,提供了更靈活的物件間通訊機制。
在 Qt 4/5/6 中,自定義事件需繼承 QEvent(Qt 3 時代使用 QCustomEvent,現已棄用)。關鍵在於指定唯一的事件類型值:
class CustomEvent : public QEvent {
public:
static Type eventType() {
static Type type = static_cast(QEvent::registerEventType());
return type;
}
CustomEvent() : QEvent(eventType()) {}
// 可攜帶自定義資料
QString message;
QVariant data;
};
關鍵點:事件類型必須在 QEvent::User (1000) 到 QEvent::MaxUser (65535) 之間。使用靜態函數 QEvent::registerEventType() 可確保類型值唯一且線程安全。
Qt 提供兩種事件傳遞方式:
QCoreApplication::sendEvent(receiver, event) — 直接呼叫接收者的 event(),事件物件通常建立在堆疊上。QCoreApplication::postEvent(receiver, event) — 將事件加入佇列稍後處理,立即返回,**事件物件必須在堆上建立**,Qt 會自動管理記憶體釋放。有兩種處理自定義事件的方式:
// 方式一:重寫 customEvent()
void CustomWidget::customEvent(QEvent *event) {
if (event->type() == CustomEvent::eventType()) {
auto *customEvent = static_cast(event);
// 處理 customEvent->message 等資料
}
}
// 方式二:重寫 event()
bool CustomWidget::event(QEvent *event) {
if (event->type() == CustomEvent::eventType()) {
auto *customEvent = static_cast(event);
// 處理邏輯
return true; // 表示已處理
}
return QWidget::event(event); // 其他事件交給父類
}
postEvent() 實現跨線程通訊,避免死鎖風險registerEventType() 避免類型衝突QString、QVariant)提升效能event() 中對未處理的事件呼叫父類實作掌握自定義事件,意味著你擁有了 Qt 事件系統的完整控制權,能夠構建更靈活、高效的多線程應用架構。