Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt: Defining a custom event type

Tags:

c++

qt

qt4

I have created a custom event in my Qt application by subclassing QEvent.

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

In order to check for this event, I use the following code in an event() method:

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

I would like to be able to define the custom event's Type somewhere in my application so that I don't need to cast the actual integer in my event methods. So in my event() methods I'd like to be able to do something like

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

Any thoughts how and where in the code I might do this?

like image 351
Chris Avatar asked Feb 11 '10 21:02

Chris


People also ask

How to use event filter in Qt?

An event filter gets to process events before the target object does, allowing it to inspect and discard the events as required. An existing event filter can be removed using the QObject::removeEventFilter() function.

What is QEvent?

The QEvent class is the base class of all event classes. Event objects contain event parameters.

Is Qt event driven?

Qt is an event-based system, and all GUI applications are event-driven. In an event-driven application, there is usually a main loop that listens for events and then triggers a callback function when one of those events is detected.

How does a Qt event loop work?

Qt's event loop starts the moment the underlying application's exec() function gets called. Once started, the loop repeatedly checks for something to happen in the system, such as user-input through keyboard/mouse.


3 Answers

If the event-type identifies your specific class, i'd put it there:

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

// usage:
if(evt->type() == MyEvent::myType) {
    // ...
}
like image 101
Georg Fritzsche Avatar answered Sep 17 '22 14:09

Georg Fritzsche


For convenience, you can use the QEvent::registerEventType() static function to register and reserve a custom event type for your application. Doing so will allow you to avoid accidentally re-using a custom event type already in use elsewhere in your application.

Example:

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;
like image 21
Ostap Avatar answered Sep 19 '22 14:09

Ostap


The idiomatic way of dealing with such problems is to create a template wrapper class, leveraging CRTP. For each custom event type, such template represents a new type, thus a separate staticType() member exists for each type, returning its unique registered type.

Below I give three ways of identifying types:

  1. By staticType() -- this is only useful within an invocation of the application, and is the type to be used with QEvent. The values are not guaranteed to stay the same between invocations of an application. They do not belong in durable storage, like in a log.

  2. By localDurableType() -- those will persist between invocations and between recompilations with the same compiler. It saves manual definition of durableType() method when defining complex events.

  3. By durableType() -- those are truly cross platform and will be the same unless you change the event class names within your code. You have to manually define durableType() if you're not using the NEW_QEVENT macro.

Both localDurableType() and durableType() differ betwen Qt 4 and 5 due to changes to qHash.

You use the header in either of two ways:

#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
like image 24
Kuba hasn't forgotten Monica Avatar answered Sep 19 '22 14:09

Kuba hasn't forgotten Monica