• Aucun résultat trouvé

Mise en œuvre avec Visual Basic

5.  Les événements

Cette  erreur  intervient  au  moment  de  l’appel  de  la  procédure  de  tri.  Les  éléments  du  tableau  que  nous  avons  passé  comme  paramètre  n’implémentent  pas  l’interface Comparable  et  nous  ne  sommes  pas  certains  qu’ils  contiennent  une  fonction  compare.  À  noter  que,  même  s’il  existe  une  fonction compare  correcte  dans  la  classe voiture,  il  faut  obligatoirement spécifier que cette classe implémente l’interface Comparable, pour que notre code puisse fonctionner. 

5. Les événements 

Les  méthodes  nous  permettent  de  communiquer  avec  les  objets  qui  composent  une  application  mais  les  objets  ont  également la possibilité de nous faire part de leurs réactions en générant des événements. Ces événements doivent  ensuite être pris en compte pour réagir à ce qui vient de se passer dans l’application. 

Les événements sont très largement utilisés dans la conception de l’interface graphique d’une application car ils nous  permettent d’avoir des informations sur les actions effectués par l’utilisateur de l’application. 

a. Déclaration et déclenchement d’événements 

Voyons,  tout  d’abord,  comment  générer  un  événement  dans  une  classe.  La  première  chose  à  faire  est  de  déclarer  l’événement  dans  la  classe.  Cette  déclaration  s’effectue  de  la  même  manière  que  celle  des  variables  internes  à  la  classe.  On  utilise  pour  cela  le  mot  clé event  suivi  du  nom  de  l’événement.  Nous  pouvons  également,  lors  de  la  déclaration, spécifier des paramètres qui fourniront des informations supplémentaires sur l’événement lui­même ou sur  l’état de l’objet, au moment où l’événement se déclenche. Nous pouvons, par exemple créer dans notre classe Client  un  événement  qui  se  déclenchera  à  chaque  ajout  d’une  nouvelle  commande.  Comme  information  supplémentaire,  notre événement fournira le nombre de commandes après l’ajout. 

Public Event NouvelleCommande(ByVal nbCommandes As integer)

Il nous reste maintenant à définir dans quelles conditions notre événement sera déclenché et bien sûr à le déclencher  à ce moment­là. Pour notre classe Client, le plus évident est de générer notre événement au moment où l’on exécute  la  méthode  permettant  d’ajouter  une  commande.  Pour  cela,  nous  allons  créer  la  méthode AjoutCommande.  Cette  méthode  reçoit  comme  paramètre  le  numéro  de  la  commande  à  ajouter.  La  seule  action  de  cette  méthode  sera  d’incrémenter le nombre de commandes du client. 

Public Sub AjoutCommande(ByVal numero As Integer) nbCommandes = nbCommandes + 1

End Sub

Dans la méthode AjoutCommande, nous allons donc déclencher l’événement avec l’instructionRaiseEvent suivie du nom  de l’événement déclaré au préalable dans la classe. Nous devons également fournir les éventuels paramètres déclarés  avec notre événement. 

Public Sub AjoutCommande(ByVal numero As Integer) nbCommandes = nbCommandes + 1

RaiseEvent NouvelleCommande(nbCommandes) End Sub

Après  l’exécution  de  l’instruction RaiseEvent,  l’événement  sera  transmis  à  tous  les  éléments  qui  se  seront  déclarés 

intéressés par cet événement. Si plusieurs éléments sont intéressés par l’événement, ils recevront les uns après les  autres la notification de l’événement. 

 À noter toutefois qu’il n’est pas possible de prédire l’ordre dans lequel les éléments de notre application seront  prévenus, ni de prévenir un nouvel élément tant que le précédent n’aura pas fini de traiter l’événement. 

b. Gérer les événements 

Regardons maintenant comment récupérer les événements dans notre application. Deux solutions sont possibles : 

déclarer une variable avec le mot clé WithEvents et utiliser la clause Handles. 

Ajouter manuellement un gestionnaire d’événement. 

 La  deuxième  solution  est  plus  souple  car  elle  nous  permettra  d’ajouter  ou  de  supprimer  dynamiquement  des  gestionnaires d’événement pendant le fonctionnement de notre application, mais elle nécessite un peu plus de  code que la première solution. 

Cette solution nécessite une déclaration de variable spécifique. La déclaration d’une variable pouvant référencer une  instance de la classe Client s’effectue de la manière suivante. 

Dim WithEvents unClient As Client

Il convient maintenant de décider quel code sera exécuté lorsque cet événement se produira. Une procédure liée à la  réception  de  cet  événement  doit  être  créée.  Pour  cela,  l’environnement  de  développement  nous  facilite  la  tâche.  En  haut de notre fenêtre de code, nous avons deux listes disponibles. 

La première nous indique toutes les sources d’événements disponibles et nous permet donc de choisir d’où proviendra  notre événement. 

 

La seconde indique, pour la source d’événement actuellement sélectionnée, quels sont les événements susceptibles  d’être déclenchés. 

 

Après  avoir  fait  notre  choix  dans  les  deux  listes,  l’environnement  génère  automatiquement  le  squelette  de  la  procédure qui sera appelée par le déclenchement de l’événement. 

Private Sub unClient_NouvelleCommande(ByVal nbCommandes As Integer) Handles unClient.NouvelleCommande

End Sub

Cette méthode est identique à celles que l’on a écrit jusqu’à présent, avec en plus le mot clé Handles suivi du nom de  l’événement qui sera traité par cette procédure. Par convention, le nom de la procédure est constitué par le nom de  l’élément suivi par le nom de l’événement géré sur cet objet. Mais ceci reste une convention permettant de faciliter la  lecture du code. La seule obligation est que la procédure respecte la signature définie dans l’événement. 

Nous pouvons également ajouter plusieurs procédures qui seront appelées par le même événement, mais il faut dans  ce cas reprendre le code manuellement et bien sûr utiliser des noms différents pour les procédures. Cette méthode  manque de souplesse car il est impossible de choisir, pendant l’exécution, quel gestionnaire d’événement sera utilisé. 

Utilisation de la clause Handles

Il  existe  également  une  autre  contrainte  liée  au  fait  que  les  variables  déclarées WithEvents  doivent  obligatoirement  être déclarées en dehors de toute procédure ou fonction. 

Pour éviter ces limitations, nous avons la possibilité d’ajouter manuellement des gestionnaires d’événement. Dans ce  cas, la variable doit être déclarée sans le mot clé WithEvents. On utilise ensuite le mot cléAddHandler pour associer à  un événement une procédure pour le gérer. 

AddHandler unClient.NouvelleCommande, AddressOf unClient_NouvelleCommande

Le  premier  paramètre  de AddHandler  est  l’événement  que  l’on  veut  gérer  puis  on  lui  indique  également,  par  l’intermédiaire de AddressOf, l’emplacement où se trouve la procédure qui sera exécutée pour gérer cet événement. 

Nous  pouvons  ainsi  décider,  au  cours  du  fonctionnement  de  l’application,  qui  gèrera  un  événement  particulier.  Par  exemple, si nous avons une application qui fonctionne en mode console ou en mode Windows, nous aurons un mode 

AddHandler unClient.NouvelleCommande, AddressOf gestion_graph Else

AddHandler unClient.NouvelleCommande, AddressOf gestion_texte End If

unClient.AjoutCommande(10)

Public Sub gestion_graph(ByVal nbcmd As Integer) MsgBox("nombre de commandes " & nbcmd) End Sub

Public Sub gestion_texte(ByVal nbcmd As Integer) Console.WriteLine(“nombre de commandes " & nbcmd) End Sub

De  la  même  manière,  nous  pouvons  supprimer  un  gestionnaire  d’événement  qui  est  déjà  référencé,  en  utilisantRemoveHandler. 

RemoveHandler unClient.NouvelleCommande, AddressOf gestion_graph

Cette  instruction  ne  supprime  pas  la  procédure gestion_graph  mais  coupe  simplement  la  liaison  avec  l’événement  leChef.augmentation_salaire. Cette liaison pourra être rétablie par la suite en utilisant à nouveau AddHandler. 

Dernier point à éclaircir : comment vont se comporter les événements lorsque notre classe sera sous­classée. 

Les  événements  suivent  les  mêmes  règles  d’héritage  que  les  propriétés  et  méthodes.  Un  événement  déclaré  dans  une  classe  sera  accessible  dans  toutes  ces  sous­classes.  Une  petite  restriction  existe  quand  même,  puisque  le  déclenchement de l’événement  pourra  n’avoir lieu que dans la classe dans laquelle il est déclaré. Pour contourner le  problème, il suffit de déclarer une méthode protected dans la classe et simplement faire déclencher l’événement par  cette méthode. Nous aurons ensuite la possibilité de déclencher l’événement dans n’importe quelle autre sous­classe,  non pas en utilisant directement le RaiseEvent, mais en utilisant la méthode protégée qui le fera pour nous. 

Par  exemple,  pour  pouvoir  déclencher  l’événement  dans  une  sous­classe  de Client  nous  pourrions  écrire  le  code  suivant : 

Dans la classe Client: 

Protected Sub declenche_NouvelleCommande(ByVal nb as integer) RaiseEvent NouvelleCommande (nb)

End sub

Dans la sous­classe de Client:  Public Sub plusUne()

...

declenche_NouvelleCommande(numero) ...

End Sub

Ajout et suppression de gestionnaire d’événement

Événements et héritage