2010-02-11 16 views
16

He creado un evento personalizado en mi aplicación Qt mediante la subclasificación QEvent.Qt: definición de un tipo de evento personalizado

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

Con el fin de comprobar si este evento, yo uso el siguiente código en un método de evento():

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

Me gustaría ser capaz de definir el tipo del evento personalizado en alguna parte de mi solicitud para que no necesite convertir el entero real en mis métodos de evento. Así que en mi evento() métodos Me gustaría ser capaz de hacer algo como

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

¿Alguna idea de cómo y en qué parte del código que podría hacer esto?

+4

En lugar de la constante mágica '2000', puede usar' QEvent :: User'. –

+2

@TonvandenHeuvel: +1. También. En lugar de "puedo usar", diría que ** debería usar **. ;) – Macke

Respuesta

15

Si el tipo de evento identifica su clase específica, que había puesto allí:

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

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

Eso ayudó mucho, ¡gracias! Aunque no entiendo completamente por qué lo hizo revisar que lo hizo. – Chris

+1

Si se inicializa en la definición de clase, se puede usar en expresiones constantes integrales como con sentencias 'case' en' switch' o como límites de matriz. –

13

Para mayor comodidad, puede utilizar la QEvent :: registerEventType() función estática para registrarse y reservar un evento personalizado escriba para su aplicación. Hacerlo le permitirá evitar volver a utilizar accidentalmente un tipo de evento personalizado que ya esté en uso en otra parte de su aplicación.

Ejemplo:

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

Esta es una buena propuesta, pero puede omitir la parte de QEvent :: None: const QEvent :: Tipo CustomEvent :: EventType = static_cast (QEvent :: registerEventType()); – gaspard

+1

Y nombrando su ejemplo QCustomEvent no es muy inteligente: es el nombre de una clase Qt 3. – gaspard

+0

Además, no necesita una variable miembro. Solo usa un local estático. –

4

La forma idiomática de tratar con estos problemas es la creación de una clase de plantilla envoltura, aprovechando CRTP. Para cada tipo de evento personalizado, dicha plantilla representa un nuevo tipo, por lo que existe un miembro staticType() independiente para cada tipo, que devuelve su tipo único registrado.

A continuación doy tres formas de identificar tipos:

  1. Por staticType() - esto sólo es útil dentro de una invocación de la aplicación, y es el tipo que se utiliza con QEvent. No se garantiza que los valores permanezcan iguales entre las invocaciones de una aplicación. Ellos no pertenecen al almacenamiento duradero, como en un registro.

  2. Por localDurableType() - aquellos persistirán entre las invocaciones y entre las recompilaciones con el mismo compilador. Guarda la definición manual del método durableType() al definir eventos complejos.

  3. Por durableType() - esas son realmente multiplataforma y serán iguales a menos que cambie los nombres de clase de evento dentro de su código. Debe definir manualmente durableType() si no está utilizando la macro NEW_QEVENT.

Tanto localDurableType() y durableType() difieren Transcurrirá Qt 4 y 5 debido a los cambios a qHash.

utiliza la cabecera de una de dos maneras:

#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

Me gusta el uso del CRTP aquí, pero me pregunto cómo se asegurará de que las variantes que utilizan 'qHash' no colisionen con los tipos de eventos existentes. – Kamajii

+0

No puede estar seguro en general, pero puede estar seguro de cualquier programa específico. Puede verificar estáticamente las colisiones y recibir una respuesta "sí, hay colisiones" o "no, no hay colisiones". Entonces, a veces el hecho de que no hay forma de saber en general no impide conocerlo en circunstancias específicas. –

+0

¿Pero no es este un punto muy importante que debería mencionarse en su respuesta? Por último, no incluye ninguna disposición contra las colisiones en su código. – Kamajii

Cuestiones relacionadas