Подтвердить что ты не робот

Qt: определение настраиваемого типа события

Я создал пользовательское событие в моем приложении Qt, выполнив подкласс QEvent.

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

Чтобы проверить это событие, я использую следующий код в методе event():

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

Я хотел бы иметь возможность определять настраиваемое событие типа где-то в моем приложении, так что мне не нужно указывать фактическое целое число в методах событий. Поэтому в моих методах event() я хотел бы сделать что-то вроде

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

Любые мысли о том, как и где в коде я могу это сделать?

4b9b3361

Ответ 1

Если тип события идентифицирует ваш конкретный класс, я бы добавил его:

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

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

Ответ 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;

Ответ 3

Идиоматическим способом решения таких проблем является создание класса оболочки шаблона, использование CRTP. Для каждого настраиваемого типа событий такой шаблон представляет новый тип, поэтому для каждого типа существует отдельный член staticType(), возвращающий свой уникальный зарегистрированный тип.

Ниже я даю три способа идентификации типов:

  • В staticType() - это полезно только при вызове приложения, и это тип, который будет использоваться с QEvent. Значения не гарантируются одинаковыми между вызовами приложения. Они не принадлежат к длительному хранению, как в журнале.

  • В localDurableType() - они будут сохраняться между вызовами и между перекомпиляциями с тем же компилятором. Он сохраняет ручное определение метода durableType() при определении сложных событий.

  • В durableType() - это действительно кросс-платформа и будет одинаковой, если вы не измените имена классов событий в вашем коде. Вы должны вручную определить durableType(), если вы не используете макрос NEW_QEVENT.

Оба 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