2010-02-11 217 views
16

我已經通過繼承QEvent在我的Qt應用程序中創建了一個自定義事件。Qt:定義自定義事件類型

class MyEvent : public QEvent 
{ 
    public: 
    MyEvent() : QEvent((QEvent::Type)2000)) {} 
    ~MyEvent(){} 
} 

爲了尋找這個事件,我用下面的代碼的事件()方法:

if (event->type() == (QEvent::Type)2000) 
{ 
    ... 
} 

我希望能夠在我的應用程序的某個地方定義自定義事件的類型所以我不需要在我的事件方法中投入實際的整數。所以在我的事件()方法,我希望能夠做到像

if (event->type() == MyEventType) 
{ 
    ... 
} 

任何思考如何以及在何處的代碼,我可能做到這一點?

+4

而不是魔術常數'2000',你可以使用'QEvent :: User'。 – 2010-02-13 12:30:04

+2

@TonvandenHeuvel:+1。也。而不是「可以使用」,我會說**應該使用**。 ;) – Macke 2013-01-28 07:23:54

回答

15

如果事件類型標識特定的類,我把它放在那裏:

class MyEvent : public QEvent { 
public: 
    static const QEvent::Type myType = static_cast<QEvent::Type>(2000); 
    // ... 
}; 

// usage: 
if(evt->type() == MyEvent::myType) { 
    // ... 
} 
+0

這幫了很多,謝謝!雖然我不完全明白你爲什麼要修改你所做的。 – Chris 2010-02-11 22:48:58

+1

如果在類定義中初始化,它可以用在整型常量表達式中,比如'switch'語句中的'case'或數組邊界。 – 2010-02-11 23:37:16

13

爲了方便,你可以使用的QEvent :: registerEventType()靜態函數來註冊和儲備自定義事件鍵入您的應用程序。這樣做可以避免意外重新使用已在應用程序其他地方使用的自定義事件類型。

例子:

class QCustomEvent : public QEvent 
{ 
public: 
    QCustomEvent() : QEvent(QCustomEvent::type()) 
    {} 

    virtual ~QCustomEvent() 
    {} 

    static QEvent::Type type() 
    { 
     if (customEventType == QEvent::None) 
     { 
      int generatedType = QEvent::registerEventType() 
      customEventType = static_cast<QEvent::Type>(generatedType); 
     } 
     return customEventType; 
    } 

private: 
    static QEvent::Type customEventType; 
}; 

QEvent::Type QCustomEvent::customEventType = QEvent::None; 
+6

這是一個很好的建議,但你可以跳過QEvent :: None部分: const QEvent :: Type CustomEvent :: EventType = static_cast (QEvent :: registerEventType()); – gaspard 2010-12-26 19:48:12

+1

並命名您的示例QCustomEvent不是很聰明:它是Qt 3類的名稱。 – gaspard 2010-12-26 19:50:31

+0

另外,你不需要一個成員變量。只需使用靜態本地。 – 2013-03-09 06:46:47

4

處理此類問題的慣用方法是創建一個模板包裝類,利用CRTP。對於每個自定義事件類型,此模板表示一種新類型,因此每個類型都存在一個單獨的成員,並返回其唯一的註冊類型。

下面我給識別類型的三種方式:

  1. 通過staticType() - 這僅是有用應用程序的調用,並且是與QEvent中使用的類型。值不保證在應用程序的調用之間保持相同的。他們不要屬於耐用的存儲,就像在日誌中。

  2. 通過localDurableType() - 這些將持續在調用和重新編譯之間使用相同的編譯器。定義複雜事件時,它保存了手動定義的durableType()方法。

  3. 通過durableType() - 這些都是真正的跨平臺,並且將是相同的,除非您更改您的代碼中的事件類名稱。如果您不使用NEW_QEVENT宏,則必須手動定義durableType()

兩個localDurableType()durableType()不同介乎Qt的4和5,由於更改qHash

您使用的標題在以下兩種方式:

#include "EventWrapper.h" 

class MyComplexEvent : public EventWrapper<MyComplexEvent> { 
    // An event with custom data members 
    static int durableType() { return qHash("MyEvent"); } 
    ... 
}; 

NEW_QEVENT(MySimpleEvent) // A simple event carrying no data but its type. 

EventWrapper。h

#ifndef EVENTWRAPPER_H 
#define EVENTWRAPPER_H 

#include <QEvent> 
#include <QHash> 

template <typename T> class EventWrapper : public QEvent { 
public: 
    EventWrapper() : QEvent(staticType())) {} 
    static QEvent::Type staticType() { 
     static int type = QEvent::registerEventType(); 
     return static_cast<QEvent::Type>(type); 
    } 
    static int localDurableType() { 
     static int type = qHash(typeid(T).name()); 
     return type; 
    } 
}; 

#define NEW_QEVENT(Name) \ 
    class Name : public EventWrapper<Name> \ 
    { static int durableType() { \ 
     static int durable = qHash(#Name); return durable; \ 
    } }; 

#endif // EVENTWRAPPER_H 
+0

我喜歡在這裏使用CRTP,但我想知道如何確保使用'qHash'的變體不會與現有事件類型相沖突? – Kamajii 2017-01-01 15:26:06

+0

你一般無法確定,但你可以確定任何特定的程序。你可以靜態檢查碰撞並得到「是的,有碰撞」或「不,沒有碰撞」的答案。所以,有時候,通常無法知道的事實並不妨礙在具體情況下了解它。 – 2017-01-03 15:39:57

+0

但是,這不是一個非常重要的問題,應該在你的回答中提及嗎?最後,在代碼中不包含任何針對衝突的規定。 – Kamajii 2017-01-03 17:07:33