4 | Cours ENPC, printemps 1999 |
Java, objets, interfaces et Internet | |
Le modèle événementielLa programmation d'interfaces graphiques recourt à la notion d'événement pour représenter les interactions entre l'interface et l'utilisateur. Le modèle événementiel de Java (version 1.1) fait intervenir trois catégories d'objets :
Les objets événementsLes événements sont des objets d'une classe dérivée de java.util.EventObject. La sous-classe java.awt.AWTEvent est celle des événements créés par des interactions avec les composantes d'interface : bouton pressé, clic souris, changement de taille des fenêtres, touches du clavier pressées, etc. Quelques unes de ses sous-classes sont : Dans une classe d'événements donnée, les événements particuliers sont identifiés par des constantes de classe. Par exemple, la classe WindowEvent définit les constantes WINDOW_CLOSING, WINDOW_ICONIFIED, WINDOW_DEICONIFIED, etc. D'autres classes d'événements peuvent être définies selon le même modèle pour représenter des situations importantes qui doivent être notifiées pour que certaines actions soient déclenchées, par exemple, quand la valeur d'une certaine variable est modifiée. Les objets récepteursUn récepteur d'événement est un objet d'une classe quelconque qui implémente une interface ...Listener, dérivée de l'interface java.util.EventListener et dépendante de la catégorie des événements notifiés :
Une telle interface déclare un certain nombre de méthodes qui doivent être implémentées par la classe du récepteur. Par exemple, l'interface ActionListener déclare la méthode void actionPerformed(ActionEvent e); L'interface MouseListener déclare les cinq méthodes suivantes : void mouseClicked(MouseEvent e); void mouseEntered(MouseEvent e); void mouseExited(MouseEvent e); void mousePressed(MouseEvent e); void mouseReleased(MouseEvent e); C'est en implémentant ces méthodes que l'on programme les actions qui doivent être effectuées quand un événement est notifié. Comme un récepteur peut recevoir la notification d'événements d'une même catégorie, mais provenant de plusieurs sources, il peut être nécessaire de tester la source de l'événement notifié : public void actionPerformed(ActionEvent e) { if (e.getSource() == ouvrir) { ouvrir(); } else if (e.getSource() == ecrire) { ecrire(); } else if (e.getSource() == sauvegarder) { sauvegarder(); } else { quitter(); } } Un objet peut être la source de plusieurs types d'événements ; pour chacun d'entre eux, il peut enregistrer plusieurs récepteurs, chacun étant responsable d'actions spécifiques. Enregistrement des récepteursLes récepteurs doivent être enregistrés par l'objet source pour être notifiés des événements dont il est à l'origine. L'enregistrement d'un récepteur se fait grâce aux méthodes add..Listener de l'objet source ; l'annulation de l'enregistrement se fait par la méthode remove...Listener correspondante : source.addActionListener(recepteur); ... source.removeActionListener(recepteur);Il est fréquent d'utiliser comme récepteur l'instance d'une classe conteneur des composantes d'interface. Dans ce cas, l'enregistrement se fait à l'aide de la référence this : source.addActionListener(this); Un exemple : les événements sourisL'applette suivante affiche la position et l'instant des événements souris.
Voici le squelette du programme [source] : public class MouseEventDemo extends Applet implements MouseListener { BlankArea zoneSource; TextArea zoneTexte; public void init() { ... // enregistrement comme recepteur des événements souris // de source zoneSource zoneSource.addMouseListener(this); } public void mousePressed(MouseEvent e) { zoneTexte.append("Mouse pressed" + ", clics = " + e.getClickCount() + ", (x, y) = (" + e.getX() + ", " + e.getY() + ")" + ", t = " + e.getWhen() + "\r\n"); } public void mouseReleased(MouseEvent e) { ... } public void mouseEntered(MouseEvent e) { ... } public void mouseExited(MouseEvent e) { ... } public void mouseClicked(MouseEvent e) { ... } } Adaptateurs et classes internesSi l'on ne s'intéresse pas à toutes les méthodes déclarées dans l'interface MouseListener, on n'est pas obligé de les implémenter toutes, mais dans ce cas, on ne doit plus spécifier implements MouseListener. On utilise alors la classe MouseAdapter qui implémente l'interface MouseListener par des méthodes vides (c'est-à-dire { ... }). Il suffit alors d'étendre cette classe en redéfinissant uniquement les méthodes auxquelles on s'intéresse. La classe dérivée est une classe interne à la classe en cours de définition, qui est capable d'accéder aux membres de la classe englobante : public class MouseEventAdapterDemo extends Applet { BlankArea zoneSource; TextArea zoneTexte; public void init() { // enregistrement d'un récepteur de classe InnerMouseAdapter // pour les événements de source zoneSource class InnerMouseAdapter extends MouseAdapter { public void mousePressed(MouseEvent e) { zoneTexte.append("Mouse pressed:" + ", t = " + e.getWhen() + newline); } } zoneSource.addMouseListener(new InnerMouseAdapter()); } } Il est possible de combiner la définition de la classe interne et son instantiation en une seule expression, dite de classe anonyme : public void init() { zoneSource.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { zoneTexte.append("Mouse pressed" + ", t = " + e.getWhen() + newline); } }); } Un exemple : les événements clavierL'applette suivante affiche les caractéristiques des événements provenant du clavier.
Voici le squelette du programme [source] : public class KeyEventDemo extends Applet implements KeyListener { TextField zoneSource; TextArea zoneTexte; public void init() { ... // enregistrement comme récepteur des événements clavier // de source zoneSource zoneSource.addKeyListener(this); } public void keyTyped(KeyEvent e) { zoneTexte.append("KEY TYPED: "); keyDisplay(e); } public void keyPressed(KeyEvent e) { ... } public void keyReleased(KeyEvent e) { ... } protected void keyDisplay(KeyEvent e){ String charString = "caractère = '" + e.getKeyChar(), keyCodeString = "code = " + e.getKeyCode(), modString = "modif. = " + e.getModifiers(); zoneTexte.append("\n" + charString + ", " + keyCodeString + ", " + modString + "\n"); } } |
[Cours Java] [Notes 3] [Notes 5]
Mise à jour :