DESS MINT |
Programmation Orientée Objets, langage Java
|
2000-2001 |
Henri Garreta
|
Les événements qui intéressent une application traduisent des actions de l'utilisateur sur les organes d'entrée (souris, clavier). Certains sont de bas niveau, comme "l'utilisateur a bougé la souris", tandis que d'autres sont très élaborés, comme "l'utilisateur a choisi la commande Enregistrer dans le menu Fichier".
Voici les principaux éléments du modèle de gestion des événements de Java (ce modèle a changé à l'occasion de la version 1.1) :
Certains objets, essentiellement les composants (classe java.awt.Component) sont des sources d'événements. Le plus souvent, dire qu'un composant a été la source d'un événement c'est dire que l'utilisateur a fait, avec la souris ou le clavier, un geste adressé à ce composant.
Les événements sont rangés en classes d'événements. Elles correspondent à des classes Java et sont très nombreuses ; par exemple :
Un événement représente généralement une requête, à laquelle il faut répondre ; nous appellerons cela "traiter l'événement".
A chaque classe d'événements sont associées une ou plusieurs interfaces qui représentent les "cahiers des charges" que devront satisfaire les objets qui prétendent pouvoir traiter ces événements lorsqu'ils se produisent.
Par exemple, à la classe MouseEvent sont associées les interfaces MouseListener (littéralement auditeur de souris) et MouseMotionListener (auditeur des mouvements de souris). L'interface MouseListener est ainsi définie :
public interface MouseListener extends EventListener { void mouseClicked(MouseEvent e); void mouseEntered(MouseEvent e); void mouseExited(MouseEvent e); void mousePressed(MouseEvent e); void mouseReleased(MouseEvent e); }
Ainsi, un objet qui prétend traiter les événements souris doit définir chacune des cinq méthodes "promises" ci-dessus. Cela doit être officialisé par le fait que sa classe déclare explicitement implémenter l'interface MouseListener.
[ Noter au passage qu'on peut "lire" ces interfaces XXXListener comme les listes des événements susceptibles d'être émis. ]
Pour chaque classe d'événements dont il peut être la source, chaque composant maintient une liste d'auditeurs, c'est-à-dire une liste d'objets, capables de traiter ces événements, qui ont demandé à être prévenus lorsque ces événements se produiraient.
Les auditeurs s'inscrivent dans ces listes en appelant une méthode de la source, nommée addXXXListener. Par exemple, pour qu'un objet b reçoive notification des événements souris ayant pour source un objet a il faut exécuter
a.addMouseListener(b);
Notez bien que :
Implicitement, le point précédent donne un moyen de trouver, dans la documentation, la liste d'événements dont un composant c peut être la source : chercher dans la classe de c les méthodes nommées addXXXListener (en général on en trouve beaucoup !), puis consulter les définitions des interfaces XXXListener correspondantes.
L'identification précise d'un événement produit se fait par le nom de la méthode appelée (exemple : mousePressed) complété par des informations qui sont dans l'argument de la méthode, dont le type dépend de la classe de l'ébvénement. Par exemple, dans le cas de MouseEvent, e.paramString() renvoie une chaîne qui permet de savoir quel bouton a été pressé, et e.getX() et e.getY() renvoient les coordonnées du point où l'événement s'est produit.
Les interfaces XXXListener sont généralement copieuses, et déclarent des méthodes pour bien plus d'événements que ceux que l'on souhaite traiter. Pour les implémenter nous devons écrire des classes avec de nombreuses fonctions creuses :
class MaGestionDeSouris implements MouseListener { public void mouseClicked(MouseEvent e) { ... quelque chose d'intéressant ... } public void mouseEntered(MouseEvent e) { /* rien */ } public void mouseExited(MouseEvent e) { /* rien */ } public void mousePressed(MouseEvent e) { /* rien */ } public void mouseReleased(MouseEvent e) { /* rien */ } }
Les adaptateurs nous évitent de telles corvées. L'adaptateur XXXAdapter est une classe (non abstraite) définissant une version par défaut de chaque méthode déclarée dans l'interface XXXListener. Il nous suffit alors de définir une classe dérivée de XXXAdapter, dans laquelle nous donnons la bonne version de la méthode qui nous intéresse :
class MaGestionDeSouris extends MouseAdapter // implemente MouseListener { public void mouseClicked(MouseEvent e) { ... quelque chose d'intéressant ... } }
Bien entenu, il faut enregistrer une instance de cette classe comme devant traiter les événements souris. Par exemple, dans un constructeur de la classe qui est la source d'événements souris, on trouvera la ligne :
addMouseListener(new MaGestionDeSouris());
En utilisant les classes dérivées anonymes on peut faire encore plus simple. Cela consiste à définir la méthode spécifique mouseClicked au moment de l'instanciation de la classe MouseAdapter. Pour l'exemple précédent : (1) il n'y a pas besoin de définir une classe MaGestionDeSouris, et (2) l'appel de addMouseListener devient :
addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { ... quelque chose d'intéressant ... } });
Fin du document annexe