C++ Qt:定义自定义事件类型

C++ Qt:定义自定义事件类型,c++,qt,qt4,C++,Qt,Qt4,我通过子类化QEvent在Qt应用程序中创建了一个自定义事件 class MyEvent : public QEvent { public: MyEvent() : QEvent((QEvent::Type)2000)) {} ~MyEvent(){} } 为了检查此事件,我在event()方法中使用以下代码: 我希望能够在我的应用程序中的某个地方定义自定义事件的类型,这样我就不需要在我的事件方法中强制转换实际的整数。因此,在我的event()方法中,我希望能够执行以下操作

我通过子类化QEvent在Qt应用程序中创建了一个自定义事件

class MyEvent : public QEvent
{
  public:
    MyEvent() : QEvent((QEvent::Type)2000)) {}
    ~MyEvent(){}
}
为了检查此事件,我在event()方法中使用以下代码:

我希望能够在我的应用程序中的某个地方定义自定义事件的类型,这样我就不需要在我的事件方法中强制转换实际的整数。因此,在我的event()方法中,我希望能够执行以下操作

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

在代码中我可以如何以及在何处这样做?

如果事件类型标识了您的特定类,我会将其放在那里:

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

// usage:
if(evt->type() == MyEvent::myType) {
    // ...
}
MyEvent类:公共QEvent{ 公众: 静态常量QEvent::Type myType=static_cast(2000); // ... }; //用法: if(evt->type()==MyEvent::myType){ // ... }
为方便起见,您可以使用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;
QCustomeEvent类:公共QEvent
{
公众:
QCustomEvent():QEvent(QCustomEvent::type())
{}
虚拟~QCustomEvent()
{}
静态QEvent::Type()类型
{
如果(customEventType==QEvent::None)
{
int generatedType=QEvent::registerEventType()
customEventType=静态_转换(generatedType);
}
返回customEventType;
}
私人:
静态QEvent::类型customEventType;
};
QEvent::Type QCustomeEvent::customEventType=QEvent::None;

处理此类问题的惯用方法是创建一个模板包装类,利用。对于每个自定义事件类型,该模板表示一个新类型,因此每个类型都有一个单独的
staticType()
成员,返回其唯一的注册类型

下面我给出了三种识别类型的方法:

  • By
    staticType()
    ——这只在应用程序调用中有用,并且是要与
    QEvent
    一起使用的类型。这些值不能保证在应用程序调用之间保持不变。它们不属于持久性存储,就像在日志中一样

  • 通过
    localDurableType()
    ——这些将在调用之间以及使用同一编译器的重新编译之间保持。定义复杂事件时,它保存了
    durableType()
    方法的手动定义

  • 通过
    durableType()
    ——这些都是真正跨平台的,除非您更改代码中的事件类名称,否则它们将是相同的。如果不使用
    NEW\QEVENT
    宏,则必须手动定义
    durableType()

  • Qt 4和Qt 5之间的
    localDurableType()
    durableType()
    由于对
    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”
    类MyComplexEvent:PublicEventWrapper{
    //具有自定义数据成员的事件
    静态int durableType(){return qHash(“MyEvent”);}
    ...
    };
    NEW_QEVENT(MySimpleEvent)//一个只携带其类型而不携带数据的简单事件。
    
    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
    
    \ifndef EVENTWRAPPER\u H
    #定义事件包装器
    #包括
    #包括
    模板类EventWrapper:公共QEvent{
    公众:
    EventWrapper():QEvent(staticType()){}
    静态QEvent::类型staticType(){
    静态int-type=QEvent::registerEventType();
    返回静态_-cast(类型);
    }
    静态int localDurableType(){
    静态int type=qHash(typeid(T).name());
    返回类型;
    }
    };
    #定义新事件(名称)\
    类名:public EventWrapper\
    {static int durableType(){\
    static int-dustable=qHash(#Name);返回dustable\
    } };
    #endif//EVENTWRAPPER\u H
    
    这帮了大忙,谢谢!虽然我不完全理解你为什么要这么做。如果在类定义中初始化,它可以用在积分常量表达式中,比如
    switch
    语句中的
    case
    ,或者用作数组边界。而不是神奇常量
    2000
    ,您可以使用
    QEvent::User
    @TonvandenHeuvel:+1。也。与其说“可以使用”,不如说“应该使用”。)这是一个很好的命题,但您可以跳过QEvent::None部分:const QEvent::Type CustomEvent::EventType=static_cast(QEvent::registerEventType());将示例命名为QCustomEvent并不是很聪明:它是Qt3类的名称。此外,您不需要成员变量。只需使用静态本地警告。这是错误的建议。只有当您有一个自定义事件类型时,此代码才有效。您不能从此
    QCustomEvent
    类派生!我喜欢在这里使用CRTP,但我想知道您如何确保使用
    qHash
    的变体不会与现有的事件类型发生冲突?一般来说,您不能确定,但您可以确定任何特定的程序。您可以静态检查碰撞,并得到“是,有碰撞”或“否,没有碰撞”的答案。所以,有时候,一般情况下没有办法知道的事实并不排除在特定情况下知道。但这不是一个非常重要的问题,应该在你的回答中提到吗?最后,您的代码中没有任何防止冲突的规定,代码本身没有太多的工作要做。您将使用静态检查器来验证是否存在冲突。
    #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