Tutoriel wxWindows
de David BEECH traduction française par Patrick VALERI
20/11/2003
Programmez avec wxWindows
Troisième Étape
Utilisation des événements
(events)
Les évènements GUI
Il y a bien des années, je travaillais sur deux types de système d'exploitation. L'un était un système à partage de temps et le planificateur du système d'exploitation donnait à chaque utilisateur un créneau horaire pendant lequel utiliser les ressources de l'ordinateur, l'autre, un système de pilotage d'évènement. C'était un contrôleur de processus industriel et le processus n'était pas en mesure d'attendre que chaque utilisateur obtienne un partage de ressources. Ce système fût conçu pour répondre rapidement aux événements extérieurs comme la fusion imminente d'un réacteur nucléaire. Par certains aspects, les systèmes GUI combinent le modèle à pilotage d'évènement avec celui à répartition de temps.
Un évènement est un fait d'une certaine importance qui est survenu en dehors du programme. Il peut avoir été provoqué par un utilisateur en sélectionnant un élément(item) du menu ou par un raccourci clavier. Il peut avoir été provoqué par quelque chose dans l'environnement de l'ordinateur mais en dehors du programme, un « timer » (ou chrono) qui s'arrête, des données arrivant sur un port de communication, un message d'arrêt du système etc. . Quelles que soient les origines de l'évènement il est nécessaire de composer avec !
Pendant que j'écris cela, j'ai 10 applications chargés sur mon système Windows 98. En dehors de cet éditeur, mes applications ne semblent pas pouvoir faire plus, de temps en temps la diode du disque dur s'allume. Cependant si je clique sur une application sur la barre des tâches cette application apparaît, prête à travailler. La barre des tâches reçoit l'évènement « clic de souris », remonte l'évènement et les informations s'y rapportant finissent dans une file d'attente gérée par le système d'exploitation et d'une façon ou d'une autre l'application appropriée obtient le message lui indiquant qu'elle est appelée.
Une technique de programmation classique pour la capture des événements est d'utiliser les fonctions de call-back . Voici un exemple d'utilisation des fonctions de call-back dans FLTK (un autre excellent framework multiple plate-forme):
Fl_Menu_Item menuitems[] =
{ { "&File", 0,0,0, FL_SUBMENU},
{ "&New", FL_ALT + 'n', (Fl_Callback *) new_cb },
...
...
void new_cb(void)
{
if (changed)
if ( !check_save() ) return;
filename[0] = '\0';
input->value("");
set_changed(0);
} |
Cette portion de programme montre un item de menu associée à une fonction « new_cb » . la fonction est conçue comme un pointeur de Fl_Callback. Quand l'application reçoit un message du système d'exploitation indiquant que l'item New a été sélectionné alors l'application peut appeler la fonction new_cb().
L' API Win32 aussi a un mécanisme similaire. Une fenêtre qui a besoin de répondre aux évènements a une fonction qui est déclarée comme une fonction de type CALLBACK. |
wxWindows et les MFC (Microsoft Foundation Classes) utilise toutes deux une technique différente, en tout cas du point de vue du programmeur. Il est bien possible que par-dessous le mécanisme de call-back soit quand même utilisé. Cela s'appelle la table des évènements et cela simplifie le travail de programmation pour la gestion des événements.
La table des évènements (events) wxWindows
BEGIN_EVENT_TABLE (BasicFrame, wxFrame)
EVT_MENU ( BASIC_EXIT, BasicFrame::OnExit)
EVT_MENU ( BASIC_ABOUT, BasicFrame::OnAbout)
EVT_MENU ( BASIC_OPEN, BasicFrame::OnOpenFile)
END_EVENT_TABLE() |
Comme vous pouvez le voir ici, la table des évènements wxWindows est la simplicité même. C'est une collection de macros, la première annonce le début de la table, les trois suivantes une constante de plusieurs types avec une méthode de classe, et la dernière annonce la fin de la table. La table des évènements relie les évènements identifiés par des constantes comme BASIC_OPEN, aux fonctions, méthodes comme BasicFrame::OnOpenFile.
Vous pouvez avoir beaucoup de tables des évènements dans votre programme aussi nous devons préciser quelle classe doit organiser les évènements pour chaque table fournie. La macro BEGIN_EVENT_TABLE déclare que la table des événements appartient à la classe BasicFrame qui est dérivé de la classe wxFrame. Nous avons besoin aussi de préciser que la classe va utiliser une table d'évènements et cela est fait avec la macro DECLARE_EVENT_TABLE() qui apparaît dans le prototype de la classe dans le fichier d'interface(ou fichier d'en-tête). Enfin nous devons fournir les fonctions membres qui vont gérer les évènements. Vous devez regarder un exemple pratique de tout ceci:
#ifndef BASIC_H
#define BASIC_H
#include <wx/wx.h>
static const wxChar
*TITLE =
_T("Basic - Step 3: Responding to events");
class BasicApplication : public wxApp
{
public:
virtual bool OnInit();
};
class BasicFrame : public wxFrame
{
public:
BasicFrame( const wxChar *title,
int xpos, int ypos,
int width, int height);
~BasicFrame();
wxTextCtrl *theText;
wxMenuBar *menuBar;
wxMenu *fileMenu;
void OnOpenFile (wxCommandEvent & event);
void OnAbout (wxCommandEvent & event);
void OnExit (wxCommandEvent & event);
DECLARE_EVENT_TABLE()
};
enum
{ BASIC_EXIT = 1,
BASIC_OPEN = 100,
BASIC_ABOUT = 200
};
#endif |
Voici le fichier d'en-tête, vous y verrez un certain nombre de nouvelles choses mais elles ne sont pas toutes reliées à un évènement.
La première chose est cette curieuse technique de travail:
static const wxChar
*TITLE =
_T("Basic - Step 3: Responding to events");
Vous avez deviné que nous déclarons un pointeur vers un char, que c'est une constante et qu'elle est statique. Dans cet exemple particulier, il n'y a pas d'autres termes pour déclarer la variable statique. La raison à cela est que nous utilisons couramment « static » pour s'assurer que la valeur est retenue entre les appels d'une fonction (internal static) ou pour cacher les variables d'autres fichiers (external static). Puisque nous n'utilisons pas d'autres fichiers dans cet exemple la classe « static » mémorisée est redondante. Néanmoins c'est un bon entraînement pour déclarer des variables externes ou globales, c.a.d variables déclarées en dehors d'une fonction, comme étant « static ». La raison est que nous devons utiliser ce fichier ailleurs et voulons exclure la possibilité d'un conflit de nom. Voyez External variables - static and automatic pour réviser les rubriques sur les variables statiques.
La macro _T est un pseudonyme pour une autre macro wxTRANSLATE qui a quelque chose à faire avec les informations locales, mais je ne sais pas encore !
Mais maintenant sur le sujet de la table des évènements:
Vous pouvez voir à gauche nous avons trois fonctions membres, chacune est une fonction void et chacune a un argument wxCommandEvent. Ce sont effectivement nos fonctions de callback. Il y a aussi une macro DECLARE_EVENT_TABLE() qui alerte le compilateur sur le fait que cette classe aura une table d'évènement. Enfin, il y a une gamme de valeurs énumérées que nous utilisons pour attribuer un identificateur de signification à des valeurs numériques. |
********************
#include "basic.h"
IMPLEMENT_APP(BasicApplication)
bool BasicApplication::OnInit()
{ ...
}
BasicFrame::BasicFrame
...
{ ...
fileMenu = new wxMenu;
fileMenu->Append(BASIC_OPEN, "&Open file");
fileMenu-> Append(BASIC_ABOUT,"&About");
fileMenu->AppendSeparator();
fileMenu->Append(BASIC_EXIT, "E&xit");
menuBar = new wxMenuBar;
menuBar->Append(fileMenu, "&File");
SetMenuBar(menuBar);
CreateStatusBar(3);
}
BasicFrame::~BasicFrame()
...
BEGIN_EVENT_TABLE (BasicFrame, wxFrame)
EVT_MENU ( BASIC_EXIT, BasicFrame::OnExit)
EVT_MENU ( BASIC_ABOUT, BasicFrame::OnAbout)
EVT_MENU ( BASIC_OPEN, BasicFrame::OnOpenFile)
END_EVENT_TABLE()
void BasicFrame::OnOpenFile (wxCommandEvent & event)
{
theText->LoadFile("data.txt");
}
void BasicFrame::OnAbout (wxCommandEvent & event)
{ wxString t = TITLE;
t.append( _T("\nDB 2001"));
wxMessageDialog
aboutDialog
( this, t, "About Basic", wxOK | wxCANCEL);
aboutDialog.ShowModal();
}
void BasicFrame::OnExit (wxCommandEvent & event)
{
Close(TRUE);
} |
Sur la gauche est le code du fichier d'implémentation. Rien n'a changé ici excepté que nous avons ajouté:
- Une table des évènements pour lier les évènements à des fonctions
- Les fonctions membres pour traiter les évènements.
Un moyen par lequel wxWindows aide les programmeurs pour s'y retrouver entre les différentes sortes d'évènements est d'apporter une provision de différentes sortes de macros. La table contient trois macros EVT_MENU() qui se répartissent spécifiquement en fonction des évènements du menu. Entre autres, les autres macros sont:
EVT_BUTTON
EVT_CHECKBOX
EVT_RADIOBUTTON
EVT_SLIDER
EVT_SCROLLBAR
Et beaucoup, beaucoup d'autres. Dans les dernières sessions nous avons appris comment utiliser les autres événements, pour l'instant nous allons juste nous concentrer sur les plus importantes.
La méthode OnOpenFile démontre combien est utile wxTextCtrl. Il a une méthode qui pourra charger directement le contenu d'un fichier dans un contrôle. Quand nous cliquons sur l'item « Open file » du menu « Fichier » cela déclenche un événement, le système d'exploitation l'intercepte et le notifie à notre application qui ainsi appelle la fonction appropriée c .a .d charger un fichier dans theText .
La méthode « OnAbout » utilise une nouvelle classe wxMessageDialog . Je vais regarder cette classe et les classes wxCommandEvent plus tard dans cette session. Pour l'instant, vous pouvez télécharger les fichiers de wxbasic3.zip si vous voulez essayer les exemples. |
********************
Sommaire
Quelque chose à faire... |
wxWindows a une macro d'évènement qui aide à la capture de redimensionnement de fenêtre:
EVT_SIZE ( BasicFrame::OnSize )
Noter qu'aucun ID d'évènement ne lui est lié puisqu'elle vérifie que cela s'applique à la fenêtre courante.
Ajouter l'évènement de redimensionnement à l'exemple, créé le traitement d'évènement OnSize et dans le traitement écrivez du code pour saisir la taille de fenêtre et l'afficher dans la barre de titre de la fenêtre bar.
Hint: Vous voudrez utiliser une wxString et la méthode wxString::Printf().
Il y a un exemple si vous êtes en panne wxbasic3a.zip . |
Bien que cela soit une session importante, je l'ai laissé brève et limité la portée de façon que vous puissiez avoir une bonne base en matière d'évènement wxWindows. La capture d'évènement peut être une affaire compliquée et même si le cadre wxWindows la rend plus facile pour le programmeur il y a encore un degré raisonnable de complexité.
Dans la prochaine session, nous verrons l'utilisation de quelques dialogues courants.
Retour en début de document
Traduction de Patrick VALERI du document de David Beech
Copyright © 1999 - 2001 David Beech
Ce document est issu de http://phenix.developpez.com/ et reste la propriété exclusive de son auteur.
La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.
Copyright © 2000-2005
|
|