Gestion des événements (suite) Exemple 1 : gérer l'événement "action sur bouton" Exemple 2 : gérer des événements "souris" de bas niveau Exemple 3 : quitter l'application quand on ferme la fenêtre graphique
Rappels Un objet source d'événements possède une liste d'objets écouteurs de ces événements instance d'une classe qui implémente l'interface ActionListener b.addActionListener(o) écouteur o b Les écouteurs s'enregistrent auprès de l'objet source
Rappels Lors d'un événement, l'objet source active la méthode appropriée de chacun des écouteurs l'utilisateur clique sur le bouton o.actionPerformed(e) écouteur o b b : - crée un ActionEvent e - pour tout écouteur o de sa liste, appelle o.actionPerformed(e) exécute actionPerformed(e)
Synthèse du mécanisme général Rappels Synthèse du mécanisme général Un objet qui peut être source d'événements possède une liste d'objets écouteurs Lorsque le système l'avertit d'une certaine action : il génère un événement d'un certain type, il déclenche la méthode appropriée (prévue dans l'interface correspondante) sur tous les objets de cette liste en passant l'événement en paramètre
Evénements de bas niveau / haut niveau Bas niveau : correspond à une action physique de l'utilisateur ex : un clic souris (MouseEvent) appui sur une touche (KeyEvent) Haut niveau : il a été "interprété" une signification lui a été donnée ex : une action sur bouton (ActionEvent) peut-être due à des événenements de bas niveau différents : un clic souris ou appui de la touche "return"
Exemple 2 : gérer des événements "souris" (dits "de bas niveau") Objet source : n'importe quel composant 2 interfaces pour les écouteurs MouseListener MouseMotionListener
Interface MouseListener void mousePressed(MouseEvent e) void mouseReleased(MouseEvent e) void mouseClicked(MouseEvent e) void mouseEntered(MouseEvent e) void mouseExited(MouseEvent e) Interface MouseMotionListener void mouseMoved(MouseEvent e) void mouseDragged(MouseEvent e)
Problème étant donnée une fenêtre contenant un panneau, réagir à certaines actions de la souris sur le panneau : souris pressée, souris relâchée, souris cliquée par un affichage dans la fenêtre console : type d'action au point x y QUI écoute? Solution 1 : un objet instance d'une classe dédiée classe externe ou interne classe interne anonyme Solution 2 : le panneau ou la fenêtre
Solution 1. Ecouteur d'une classe dédiée On doit implémenter 5 méthodes alors 3 seulement nous intéressent... Notion de classe "adapteur" : classe qui implémente l'interface avec un corps vide pour chaque méthode Il existe une classe adapteur pour la plupart des interfaces qui spécifient plusieurs méthodes
public abstract class MouseAdapter extends Object implements MouseListener An abstract adapter class for receiving mouse events. The methods in this class are empty. This class exists as convenience for creating listener objects. Mouse events let you track when a mouse is pressed, released, clicked, when it enters a component, and when it exits. (To track mouse moves and mouse drags, use the MouseMotionAdapter.) Extend this class to create a MouseEvent listener and override the methods for the events of interest. (If you implement the MouseListener interface, you have to define all of the methods in it. This abstract class defines null methods for them all, so you can only have to define methods for events you care about.)
Solution 2. La fenêtre ou le panneau écoute Pas d'héritage multiple : les classes Fenêtre (dérivée de JFrame) et PanneauSouris (dérivée de JPanel) ne peuvent donc dériver aussi de la classe MouseAdapter Une classe d'écouteur dédiée (anonyme ou non) est donc plus commode ici
Exemple 3 : quitter l'application quand on ferme la fenêtre graphique Créer un écouteur des événements sur cette fenêtre
Interface WindowListener
public class Fenetre extends JFrame { …………… public Fenetre() // constructeur Terminator t = new Terminator(); addWindowListener(t); } ……… Ecrivons la classe Terminator
public class Terminator implements WindowListener { public void windowClosing (WindowEvent e) { System.exit(0); } // et les 6 autres méthodes avec un corps vide } Ouf! On a la classe WindowAdapter public class Terminator extends WindowAdapter { public void windowClosing (WindowEvent e) { System.exit(0); } }
Revenons à la classe Fenetre : public Fenetre() // constructeur { …………… Terminator t = new Terminator(); addWindowListener(t); } La référence t n'est pas utile addWindowListener(new Terminator()); Le nom Terminator non plus…. on fait de Terminator une classe interne anonyme
public class Terminator extends WindowAdapter { public void windowClosing (WindowEvent e) { System.exit(0); } } addWindowListener( new Terminator()); devient : addWindowListener( new WindowAdapter() { public void windowClosing (WindowEvent e) { System.exit(0); } } );
Et si c'était la fenêtre qui écoutait ses propres événements? public class Fenetre extends JFrame implements WindowListener { …………… public Fenetre() // constructeur { addWindowListener(this); } public void windowClosing (WindowEvent e) { System.exit(0); } // et les 6 autres méthodes de l'interface WindowListener avec un corps vide ………
Remarque : La classe JFrame fournit aussi la méthode Remarque : La classe JFrame fournit aussi la méthode setDefaultCloseOperation(...) ex: setDefaultCloseOperation(EXIT_ON_CLOSE);