2010-02-11 5 views
16

J'ai créé un événement personnalisé dans mon application Qt en sous-classe QEvent.Qt: Définition d'un type d'événement personnalisé

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

Pour vérifier cet événement, j'utilise le code suivant dans une méthode d'événement():

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

Je voudrais pouvoir définir quelque part Type de l'événement personnalisé dans mon application de sorte que je n'ai pas besoin de lancer l'entier réel dans mes méthodes d'événement. Donc, dans mon événement() méthodes que je voudrais être en mesure de faire quelque chose comme

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

Toute pensée comment et où dans le code que je pourrais le faire?

+4

Au lieu de la constante magique '2000', vous pouvez utiliser' QEvent :: User'. –

+2

@TonvandenHeuvel: +1. Aussi. Au lieu de "peut utiliser", je dirais ** devrait utiliser **. ;) – Macke

Répondre

15

Si le type d'événement identifie votre classe spécifique, je mettrais là:

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

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

Cela a beaucoup aidé, merci! Bien que je ne comprends pas entièrement pourquoi vous avez fait la révision que vous avez faite. – Chris

+1

Si elle est initialisée dans la définition de classe, elle peut être utilisée dans des expressions constantes intégrales comme avec des instructions 'case' dans des commandes' switch' ou comme des limites de tableau. –

13

Pour plus de commodité, vous pouvez utiliser le QEvent :: registerEventType() fonction statique pour enregistrer et réserver un événement personnalisé tapez pour votre application. Cela vous permettra d'éviter de réutiliser accidentellement un type d'événement personnalisé déjà utilisé ailleurs dans votre application.

Exemple:

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

Ceci est une bonne proposition, mais vous pouvez ignorer la partie QEvent :: None: const QEvent :: Type CustomEvent :: EventType = static_cast (QEvent :: registerEventType()); – gaspard

+1

Et en nommant votre exemple QCustomEvent n'est pas très intelligent: c'est le nom d'une classe Qt 3. – gaspard

+0

De plus, vous n'avez pas besoin d'une variable membre. Utilisez simplement un local statique. –

4

La façon idiomatiques de faire face à ces problèmes est de créer une classe wrapper de modèle, en tirant parti CRTP. Pour chaque type d'événement personnalisé, ce modèle représente un nouveau type. Il existe donc un membre staticType() distinct pour chaque type, renvoyant son type enregistré unique.

Ci-dessous je donne trois façons de types d'identification:

  1. Par staticType() - c'est utile dans les une invocation de l'application, et est le type à utiliser avec QEvent. Les valeurs ne sont pas garanties pour rester les mêmes entre les invocations d'une application. Ils ne font pas appartiennent à un stockage durable, comme dans un journal.

  2. Par localDurableType() - ceux-ci persisteront entre les invocations et entre les recompilations avec le même compilateur. Il sauvegarde la définition manuelle de la méthode durableType() lors de la définition d'événements complexes.

  3. Par durableType() - ceux-ci sont vraiment multi-plateforme et seront les mêmes à moins que vous ne changiez les noms de classe d'événement dans votre code. Vous devez définir manuellement durableType() si vous n'utilisez pas la macro NEW_QEVENT.

Les deux localDurableType() et durableType() diffèrent Qt 4 et Situés entre 5 en raison des changements à qHash.

Vous utilisez l'en-tête de deux façons:

#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

J'aime l'utilisation du CRTP ici mais je me demande comment vous serez sûr que les variantes utilisant 'qHash' ne se heurtent pas aux types d'événements existants? – Kamajii

+0

Vous ne pouvez pas être sûr en général, mais vous pouvez être sûr de n'importe quel programme spécifique. Vous pouvez vérifier statiquement les collisions et obtenir une réponse «oui, il y a des collisions» ou «non, il n'y a pas de collisions». Ainsi, parfois le fait qu'il n'y a aucun moyen de savoir en général n'empêche pas de le savoir dans des circonstances spécifiques. –

+0

Mais n'est-ce pas un point très important qui devrait être mentionné dans votre réponse? Enfin, vous n'incluez aucune disposition contre les collisions dans votre code. – Kamajii

Questions connexes