2013-10-02 9 views
1

Je dois créer un 2 événements personnalisés. J'ai suivi ce lien & fait mon code: -
Is there a cleaner way to register Qt custom events?créer & poster le Qevent personnalisé

Est-ce la bonne façon de créer & après & passer quelques données (QString) à l'événement personnalisé?

============================================== =============

code Modifier comme par Kuba Ober sugession: ---

mainwindow.h: -

UpdateEvent *myUpdateEvent ; 
ClearEvent *myClearEvent ; 

Mainwindow.c: - -

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow) 
{ 
    ui->setupUi(this); 

    i =0; 
    myUpdateEvent = new UpdateEvent("hello"); 
    myClearEvent = new ClearEvent("bye"); 

    QCoreApplication::postEvent(this, myUpdateEvent); 
    QCoreApplication::postEvent(this, myClearEvent); 


} 

bool MainWindow::eventFilter(QObject *obj, QEvent *event) 
{ 

    qDebug() << "oo"; 
    if (UpdateEvent::is(event)) { 
     UpdateEvent *tempUpdateEvent = static_cast<UpdateEvent *>(event); 
     qDebug() << tempUpdateEvent->value(); 

    } 
    else if (ClearEvent::is(event)) { 
     ClearEvent *tempClearEvent = static_cast<ClearEvent *>(event); 
     qDebug() << tempClearEvent->value(); 

    } 

    return true; 

} 

fichier event.h: -

template <typename T> class StringEvent : public QEvent 
{ 
    QString m_str; 
public: 
    explicit StringEvent(const QString val) : QEvent(staticType()), m_str(val) 
    { 
    } 

    QString setvalue(QString val) 
    { 
     m_str = val; 
    } 

    QString value() const 
    { 
     return m_str; 
    } 

    static QEvent::Type staticType() 
    { 
     static int type = QEvent::registerEventType(); 
     return static_cast<QEvent::Type>(type); 

    } 

    static bool is(const QEvent * ev) 
    { 
     return ev->type() == staticType(); 
    } 
}; 

class UpdateEvent : public StringEvent<UpdateEvent> 
{ 
public: 
    explicit UpdateEvent(QString val): StringEvent(val) 
    { 

    } 

}; 

class ClearEvent : public StringEvent<ClearEvent> 
{ 
public: 
    explicit ClearEvent(QString val): StringEvent(val) 
    { 

    } 
}; 

Pourquoi eventFilter n'est pas déclenché? Et je ne suis pas en mesure de voir le message de débogage sur postevent?

Répondre

0

Je ne peux que commenter l'odeur de code de votre implémentation d'événement, car il est difficile de savoir pourquoi envoyer des événements à un contrôle d'édition dans une fenêtre. Ce dernier est un mauvais design.

Votre classe d'événement est inutilement compliquée. Vous devriez configurer toutes les valeurs à l'intérieur de l'événement pendant la construction, et elles devraient être accessibles par le biais d'accesseurs en lecture seule après. Le type d'événement supplémentaire semble également être un gadget inutile.

Voici comment je le ferais, en utilisant un modèle de méta-usine (un nom que j'ai inventé, peut-être y at-il un nom meilleur/existant?). Cela résout le besoin d'injection de constructeur de classe dérivée explicite qui serait autrement nécessaire. J'ai divisé la metafactory en petites classes constituantes pour faciliter la compréhension.

// A type-identifier-generating wrapper for events 
template <typename D> class EventWrapper : public QEvent { 
public: 
    EventWrapper() : QEvent(staticType()) {} 
    static QEvent::Type staticType() { 
     static QEvent::Type type = static_cast<QEvent::Type>(registerEventType()); 
     return type; 
    } 
    static bool is(const QEvent * ev) { return ev->type() == staticType(); } 
    static D* cast(QEvent * ev) { return is(ev) ? static_cast<D*>(ev) : 0; } 
}; 

// The generic event metafactory for C++98 (doesn't need C++11) 
template <typename D, template <typename> class Carrier> class EventMF { 
    class EventFwd; 
    class Final; 
    class FinalWrapper : public EventWrapper<EventFwd>, public virtual Final {}; 
public: 
    // EventFwd is a class derived from Event. The EventWrapper's cast() 
    // will cast to a covariant return type - the derived class. That's OK. 
    typedef Carrier<FinalWrapper> Event; 
private: 
    class EventFwd : public Event {}; 
    class Final { 
     friend class FinalWrapper; 
     friend class Carrier<FinalWrapper>; 
    private: 
     Final() {} 
     Final(const Final &) {} 
    }; 
}; 

// A string carrier 
template <typename B> class StringData : public B { 
    QString m_str; 
public: 
    explicit StringData(const QString & str) : m_str(str) {} 
    QString value() const { return m_str; } 
}; 

// A string event metafactory 
template <typename D> class StringEventMF : public EventMF<D, StringData> {}; 

class Update : public EventMF<Update, StringData> {}; // using generic metafactory 
class Clear : public StringEventMF<Clear> {}; // using specific metafactory 
#if 0 
// This should fail at compile time as such derivation would produce classes with 
// duplicate event types. That's what the Final class was for in the matafactory. 
class Error : public Update::Event { Error() : Update::Event("") {} }; 
#endif 

int main(int, char**) 
{ 
    // Test that it works as expected. 
    Update::Event update("update"); 
    Clear::Event clear("clear"); 
    Q_ASSERT(Update::Event::staticType() != Clear::Event::staticType()); 
    Q_ASSERT(Update::Event::staticType() == Update::Event::cast(&update)->staticType()); 
    qDebug() << Update::Event::cast(&update)->value(); 
    Q_ASSERT(Update::Event::cast(&clear) == 0); 
    qDebug() << Clear::Event::cast(&clear)->value(); 
    Q_ASSERT(Clear::Event::cast(&update) == 0); 
} 

Les classes sont Metafactory::Eventles classes d'événements personnalisés qui dérivent de QEvent. La hiérarchie de classes pour mise à jour :: Event se présente comme suit (allant du moins dérivé à la classe la plus dérivée):

  • EventWrapper<EventMF<...>::EventFwd>, EventMF<...>::Final (héritage multiple)
  • EventMF<Update, StringData<Update>>::FinalWrapper
  • StringData<Update> = EventMF<Update, StringData<Update>>::Event

    avec EventMF<...> étant un raccourci pour EventMF<Update, StringData<Update>.

La ligne Update::Event update("update") construit un événement chaîne porteuse personnalisée par exemple, avec les constructeurs appelés de la dernière à la première dans la liste ci-dessus.

Puisque EventMF<...> est une métafactory qui fonctionne uniquement au moment de la compilation, il n'est absolument pas nécessaire que son instance existe au moment de l'exécution. Ainsi, le constructeur EventMF<...>::EventMF n'est jamais appelé. Vous pouvez appliquer cet invariant en supprimant le constructeur (en le déclarant privé pour C++ 98).

L'utilisation dans un gestionnaire d'événements ressemblerait à ceci:

+0

merci .. beaucoup appris C++ concept de fil de ce dernier ... metafactory chose signifie classe dans une classe? – Katoch

+0

@Katoch: Une metafactory est une classe qui produit d'autres classes pour vous. Ici, 'Update' et' Clear' sont des métafactories qui génèrent la classe 'Event' imbriquée correcte pour vous, à chaque point d'utilisation. J'ai [posé une autre question] (http://stackoverflow.com/q/19187469/1329652) pour obtenir des commentaires de la communauté sur la façon de le faire. –

+0

Je vais suggérer que notre travail aurait également été fait sans utiliser la classe template ... parce que nous n'utilisons pas du tout la variable template T dans notre classe d'événements string ... comme le montre cet exemple ... http: // www .cprogramming.com/tutorial/templates.html .... que dites-vous ...? – Katoch