Qt:定义自定义事件类型

Posted

技术标签:

【中文标题】Qt:定义自定义事件类型【英文标题】:Qt: Defining a custom event type 【发布时间】:2010-02-11 21:54:40 【问题描述】:

我通过继承 QEvent 在我的 Qt 应用程序中创建了一个自定义事件。

class MyEvent : public QEvent

  public:
    MyEvent() : QEvent((QEvent::Type)2000)) 
    ~MyEvent()

为了检查这个事件,我在 event() 方法中使用了以下代码:

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

  ...

我希望能够在我的应用程序中的某处定义自定义事件的类型,这样我就不需要在我的事件方法中转换实际的整数。所以在我的 event() 方法中,我希望能够做类似的事情

if (event->type() == MyEventType)

  ...

有什么想法可以在代码中如何以及在何处执行此操作?

【问题讨论】:

你可以使用QEvent::User,而不是魔术常数2000 @TonvandenHeuvel:+1。还。我会说应该使用,而不是“可以使用”。 ;) 【参考方案1】:

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

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

// usage:
if(evt->type() == MyEvent::myType) 
    // ...

【讨论】:

帮助很大,谢谢!虽然我不完全理解你为什么要修改你所做的。 如果在类定义中初始化,它可以用在整数常量表达式中,比如switch语句中的case或作为数组边界。【参考方案2】:

为方便起见,您可以使用 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;

【讨论】:

这是一个不错的提议,但是您可以跳过 QEvent::None 部分: const QEvent::Type CustomEvent::EventType = static_cast<:type>(QEvent::registerEventType()) ; 并且命名您的示例 QCustomEvent 不是很聪明:它是 Qt 3 类的名称。 另外,您不需要成员变量。只需使用静态本地。 警告 这是一个糟糕的建议。仅当您有一种自定义事件类型时,此代码才有效。你不能从这个QCustomEvent 类派生!【参考方案3】:

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

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

    staticType() -- 这仅在应用程序调用中有用,并且是与QEvent 一起使用的类型。在应用程序的调用之间,值不保证保持不变。它们属于持久存储,例如日志。

    localDurableType() 提供——这些将在调用之间以及使用相同编译器的重新编译之间持续存在。在定义复杂事件时节省了手动定义durableType()方法。

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

由于qHash 的更改,localDurableType()durableType() 在 Qt 4 和 5 之间有所不同。

您可以通过以下两种方式之一使用标题:

#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

【讨论】:

我喜欢这里使用 CRTP,但我想知道您如何确保使用 qHash 的变体不会与现有事件类型发生冲突? 一般情况下您无法确定,但您可以确定任何特定程序。您可以静态检查碰撞并得到“是的,有碰撞”或“不,没有碰撞”的答案。因此,有时无法在一般情况下知道这一事实并不排除在特定情况下知道它。 但这不是您回答中应该提到的非常重要的一点吗?最后,您没有在代码中包含任何防止冲突的规定。 代码本身没什么大不了的。您将使用静态检查器来验证是否存在碰撞。

以上是关于Qt:定义自定义事件类型的主要内容,如果未能解决你的问题,请参考以下文章

第四十四课发送自定义事件(下)

Qt发送事件与自定义事件

将自定义 QEvent 传播到 Qt/PyQt 中的父小部件

Qt__自定义事件

【WPF】自定义标题栏

请教关于WPF上自定义控件添加事件的问题