wxDev.fr, le portail francophone consacré à wxWidgets ! ( The french portal for wxWidgets )  
Esp. membre
Recheche rapide



Recherche avancée
Statistiques
Membres inscrits :2359

Membres en ligne : 0
Invités en ligne : 2
Pub hébergeur
Pourquoi cette pub ?

Valid XHTML 1.0 Transitional

Valid CSS2

Menu Snippets (navigation):
Pages: 1    Accueil » Snippets » Système
» [wxEvent] : Créer un nouveau type d'événement (méthode 1)
Détails du snippet : [wxEvent] : Créer un nouveau type d'événement (méthode 1)
Informations sur l'auteur de ce snippet :


Hors ligne
Xaviou (Administrateur)
Lieu: Annecy (74)
Inscrit le : 27-08-2007
Messages: 1367
Snippets: 25
Tutoriels: 6
Introduction / Description :
Bonjour à tous.

Voici une méthode simple, mais efficace, pour créer de nouveaux types d'événements.
Cette méthode ne permet pas de "transporter" des données par l'intermédiaire de ce nouveau type d'événement.

Par exemple, une classe dérivée de wxThread va pouvoir informer le thread principal (celui gérant l'interface) qu'il a commencé à travailler, qu'il a fini, ...
Si vous créez une nouvelle classe de bouton révolutionnaire, vous allez pouvoir créer un nouveau type comme le wxEVT_COMMAND_BUTTON_CLICKED pour les wxButtons classiques.
Contenu du snippet :
Tout d'abord, la théorie :
- Il faut créer un nouvel ID pour pouvoir identifier notre type d'événement par rapport aux autres, et il faut bien entendu que cet ID soit unique, pour éviter les éventuelles confusions. wxWidgets possède pour cela une fonction ( wxNewEventType() ) qui permet de le faire automatiquement.
- Nous n'aurons pas besoin de créer une nouvelle classe d'événement : le wxCommandEvent suffira amplement.
- Nous pourrons par contre créer la macro permettant d'utiliser notre nouveau type dans une table d'événements classique (c'est à dire comprise entre les macros BEGIN_EVENT_TABLE() et END_EVENT_TABLE() ).

Voici le code à placer dans le fichier header de votre wxThread ou de votre bouton révolutionnaire (les noms ne sont bien entendu que des exemples):

Code wxWidgets:

 
// Le nouveau type permettant à un wxThread de signaler qu'il a commencé à travailler
extern const wxEventType wxEVT_MYTHREAD_STARTED;
// Le nouveau type permettant à un wxThread de signaler qu'il a terminé son boulot
extern const wxEventType wxEVT_MYTHREAD_ENDED;
 
// La macro permettant d'utiliser le type wxEVT_MYTHREAD_STARTED dans une table classique
#define EVT_MYTHREAD_STARTED(id, fn) \
    DECLARE_EVENT_TABLE_ENTRY( wxEVT_MYTHREAD_STARTED, id, wxID_ANY, \
    (wxObjectEventFunction)(wxEventFunction) wxStaticCastEvent( wxCommandEventFunction, &fn ), \
    (wxObject *) NULL ),
// La macro permettant d'utiliser le type wxEVT_MYTHREAD_ENDED dans une table classique
#define EVT_MYTHREAD_ENDED(id, fn) \
    DECLARE_EVENT_TABLE_ENTRY( wxEVT_MYTHREAD_ENDED, id, wxID_ANY, \
    (wxObjectEventFunction)(wxEventFunction) wxStaticCastEvent( wxCommandEventFunction, &fn ), \
    (wxObject *) NULL ),
 

Il est à noter que les deux macros définies ci-dessus ne sont pas obligatoires. Vous n'en n'aurez pas besoin si vous utilisez la connexion dynamique d'événements grâce à la méthode wxEventHandler::Connect().

Et voici maintenant le code à placer dans le fichier source du wxThread ou du nouveau bouton : il s'agit tout simplement de la définition des nouveaux types d'événements.

Code wxWidgets:

// Définition des nouveaux types d'événements
const wxEventType wxEVT_MYTHREAD_STARTED = wxNewEventType();
const wxEventType wxEVT_MYTHREAD_ENDED = wxNewEventType();

Et c'est tout.

Voyons maintenant comment utiliser ces nouveaux types d'événements.
Admettons que l'on veuille connecter tous les démarrages de notre classe dérivée de wxThread à une même méthode événementielle de notre wxFrame, et que l'on veuille connecter les "fins de travaux" de deux wxThreads différents ayant les identifiants ID_THREAD1 et ID_THREAD2.

Tout d'abord, l'utilisation "classique" d'une table d'événements :

Code wxWidgets:

BEGIN_EVENT_TABLE( MyFrame, wxFrame)
    EVT_MYTHREAD_STARTED(wxID_ANY, MyFrame::OnMyThreadStarted)
    EVT_MYTHREAD_ENDED(ID_THREAD1, MyFrame::OnMyThread1Ended)
    EVT_MYTHREAD_ENDED(ID_THREAD2, MyFrame::OnMyThread2Ended)
END_EVENT_TABLE()
 
// ...
 
void MyFrame::OnMyThreadStarded(wxCommandevent &event)
{
    // Cette méthode sera appelée chaque fois qu'un événement wxEVT_MYTHREAD_STARTED sera
    // envoyé à la wxFrame
}
 
void MyFrame::OnMyThread1Ended(wxCommandEvent &event)
{
    // Cette méthode sera appelée chaque fois qu'un événement wxEVT_MYTHREAD_ENDED ayant
    // l'id ID_THREAD1 sera envoyé à la wxFrame
}
 
void MyFrame::OnMyThread2Ended(wxCommandEvent &event)
{
    // Cette méthode sera appelée chaque fois qu'un événement wxEVT_MYTHREAD_ENDED ayant
    // l'id ID_THREAD2 sera envoyé à la wxFrame
}
 


Maintenant, l'utilisation de la connexion dynamique : les méthodes événementielles correspondent exactement à celles indiquées ci-dessus. Seule la méthode de connexion change.

Code wxWidgets:

// Placez par exemple les lignes suivantes dans le constructeur de la fenêtre
MyFrame::MyFrame(......)
{
    // ...
    // Connexion dynamique de l'événement "démarrage" d'un thread
    Connect(wxID_ANY, wxEVT_MYTHREAD_STARTED, wxCommandEventHandler(MyFrame::OnMyThreadStarded));
    // Connexion dynamique des événements "fin de travail"
    Connect(ID_THREAD1, wxEVT_MYTHREAD_ENDED, wxCommandEventHandler(MyFrame::OnMyThread1Ended));
    Connect(ID_THREAD2, wxEVT_MYTHREAD_ENDED, wxCommandEventHandler(MyFrame::OnMyThread2Ended));
}
 


Voyons maintenant comment "envoyer" un événement depuis notre wxThread. Dans cet exemple, un pointeur vers la fenêtre "parente" est passé au wxThread qui le stocke dans une variable wxWindow* m_parent.

Code wxWidgets:

// La fonction appelée lorsque l'on fait un wxThread::Run()
void* MyThread::Entry()
{
    // Indiquons à l'interface que l'on commence à bosser
    wxCommandEvent evt(wxEVT_MYTHREAD_STARTED, GetId());
    if(m_parent!=NULL) m_parent->GetEventHandler()->AddPendingEvent(evt);
 
    // On place ici le code effectuant le travail pour lequel le wxThread a été créé
 
    // Quand le boulot est terminé, on en informe l'interface avant de sortir
    wxCommandEvent evt(wxEVT_MYTHREAD_ENDED, GetId());
    if(m_parent!=NULL) m_parent->GetEventHandler()->AddPendingEvent(evt);
    // On peut maintenant sortir de la fonction de travail
    return NULL;
}

Le thread devra bien entendu avoir été créé avec l'identifiant ID_THREAD1 ou ID_THREAD2 pour que l'événement de fin de travail soit intercepté correctement.
Explications finales :
Voilà, c'est tout pour cette méthode.

Je le répète, elle ne permet pas de "transférer" des données par l'intermédiaire de l'événement. Pour cela, il va falloir créer notre propre classe (dérivée de wxCommandEvent) afin de pouvoir lui passer des données avant de poster l'événement.

Mais cela sera le sujet d'un autre snippet.

Bonne prog, et @+

Xav'
Commentaires
k3nrdx (Membre)
Inscrit le : 06-03-2009
Messages: 19
Snippets: 0
Tutoriels: 0
Hors ligne
Snippet clair, et interessant.

Xaviou a écrit:
Je le répète, elle ne permet pas de "transférer" des données par l'intermédiaire de l'événement. Pour cela, il va falloir créer notre propre classe
Tu parle d'objet a transférer ou de simple donnée, exemple wxString ?
Car on peut faire passé des données comme ça, non ?

wxCommandEvent evt(wxEVT_MYTHREAD_STARTED, GetId());
    evt.SetString(pMessage);
     if(m_parent!=NULL) m_parent->GetEventHandler()->AddPendingEvent(evt);
Xaviou (Administrateur)
Lieu: Annecy (74)
Inscrit le : 27-08-2007
Messages: 1367
Snippets: 25
Tutoriels: 6
Site web
Hors ligne
Salut.
Je parle en effet de données plus complexes.
Pour un wxString, cette méthode est amplement suffisante.

Il faut que je rédige le snippet pour la méthode n°2 qui le permet (créer une classe dérivée de wxCommandEvent).

@+
Xav'

Le nouveau portail wxWidgets francophone : www.wxdev.fr
Ben en fait, vous y êtes déjà...
Menu Snippets (navigation):
Pages: 1    Accueil » Snippets » Système
» [wxEvent] : Créer un nouveau type d'événement (méthode 1)