Programmation Java Swing/Gestion des évènements

Un composant peut recevoir divers évènements issus de l'interaction avec l'utilisateur :

  • Avec la souris : enfoncement et relâchement d'un bouton, déplacement de la souris, défilement de la molette.
  • Avec le clavier : enfoncement et relâchement d'une touche, génération d'un caractère.
  • Avec d'autres périphériques d'entrée.

Il peut aussi en générer :

  • Un bouton peut notifier le déclenchement d'une action.
  • La sélection d'un item dans une liste peut déclencher un évènement.
  • ...

Principes de gestion des évènements

modifier

De manière générale, la gestion des évènements en Java se fait de la manière suivante :

  • Les classes voulant recevoir une notification d'un évènement enregistrent un écouteur auprès de la source d'évènements. L'écouteur est un objet dont la classe implémente une interface particulière pour traiter un évènement comportant en général une seule méthode appelée pour notifier l'évènement qui s'est produit.
  • La source d'évènement (un composant, un périphérique d'entrée : souris ou clavier, ...) notifie les écouteurs enregistrés en appelant la méthode de l'interface particulière. Cette méthode ne comporte en général qu'un seul argument dont la classe dérive de la classe java.util.EventObject.

L'exemple ci-dessous illustre comment recevoir un évènement d'action sur un bouton, qui se déclenche au clic avec la souris, ou au clavier quand le bouton a le focus.

JButton b_ok = new JButton("OK");
b_ok.addActionListener(new ActionListener()
{
	@Override
	public void actionPerformed(ActionEvent e)
	{
		// ... Action du bouton OK ici
		System.out.println("Clic du bouton OK");
	}
});

La convention de gestion des évènements est basée sur celle des JavaBeans. Pour un évènement de type type (MouseWheel, Key, Mouse, ...) :

  • Une classe d'évènement typeEvent dérivant de la classe java.util.EventObject contient toutes les informations sur l'évènement notifié.
  • Un écouteur doit implémenter l'interface typeListener dont la ou les méthode(s) ont comme seul argument un objet de classe typeEvent.
  • La source d'évènement possède deux méthodes publiques :
    • addtypeListener pour ajouter un écouteur de l'évènement.
    • removetypeListener pour retirer un écouteur.
  • En général, en interne, la source d'évènement notifie les écouteurs enregistrés avec une méthode privée ou protégée nommée firetypeEvent.

Les différents types d'évènements

modifier

Il existe un grand nombre de types d'évènements représentés par des classes dérivant de la classe java.util.EventObject. Cette section ne citera que les principaux types parmi ceux concernant les interfaces graphiques avec Swing.

La hiérarchie des types d'évènements contient un certain nombre de classes, chacune pouvant ajouter une ou plusieurs informations sur l'évènement.

Classe Information(s) sur l'évènement définie(s)/ajoutée(s) par la classe
java.util.EventObject Source de l'évènement : public Object getSource();
└─ java.awt.AWTEvent Identification de l'évènement (ID), consommation de l'évènement
├─ java.awt.event.ActionEvent Heure de l'évènement et modificateurs (boutons de souris, touches enfoncées : Shift, Alt, Ctrl...)
(ID: ACTION_PERFORMED)
└─ java.awt.event.ComponentEvent Composant source de l'évènement (conversion de type)
└─ java.awt.event.InputEvent Heure de l'évènement et modificateurs (boutons de souris, touches enfoncées : Shift, Alt, Ctrl...)
├─ java.awt.event.KeyEvent Code de la touche, caractère généré
(ID: KEY_TYPED, KEY_PRESSED, KEY_RELEASED)
└─ java.awt.event.MouseEvent Position de la souris, nombre de clics, indicateur de menu popup
(ID: MOUSE_CLICKED, MOUSE_PRESSED, MOUSE_RELEASED, MOUSE_MOVED, MOUSE_ENTERED, MOUSE_EXITED, MOUSE_DRAGGED, MOUSE_WHEEL)
└─ java.awt.event.MouseWheelEvent Rotation de la molette de la souris (nombre, pixels de défilement)

Les sous-classes de la classe java.awt.AWTEvent ont un attribut (ID) qui identifie une notification particulière d'un évènement, chacune correspondant à une méthode de l'interface d'écoute de l'évènement. Par exemple, pour les évènements provenant de la souris, les méthodes de l'interface java.awt.event.MouseListener sont appelées avec un objet évènement de classe java.awt.event.MouseEvent dont la valeur de l'identificateur (ID) correspond à celles-ci :

public void mouseReleased(MouseEvent e); // e.getID() == MouseEvent.MOUSE_RELEASED
public void mousePressed(MouseEvent e);  // e.getID() == MouseEvent.MOUSE_PRESSED
public void mouseExited(MouseEvent e);   // e.getID() == MouseEvent.MOUSE_EXITED
public void mouseEntered(MouseEvent e);  // e.getID() == MouseEvent.MOUSE_ENTERED
public void mouseClicked(MouseEvent e);  // e.getID() == MouseEvent.MOUSE_CLICKED

Même principe pour les méthodes de l'interface java.awt.event.MouseMotionListener pour intercepter les évènements de mouvement de la souris :

public void mouseMoved(MouseEvent e);   // e.getID() == MouseEvent.MOUSE_MOVED    (Souris déplacée sans bouton enfoncé)
public void mouseDragged(MouseEvent e); // e.getID() == MouseEvent.MOUSE_DRAGGED  (Souris déplacée avec bouton enfoncé)

Cela s'applique aussi aux interfaces qui n'ont qu'une seule méthode, comme l'interface java.awt.event.MouseWheelListener pour la notification de rotation de molette de la souris :

public void mouseWheelMoved(MouseWheelEvent e); // e.getID() == MouseEvent.MOUSE_WHEEL

Cette redondance apparente d'identification du type d'évènement (par la méthode appelée et par la valeur de l'attribut ID) facilite la réutilisation d'une même méthode pour traiter plusieurs évènements de façon similaire.

Implémentation partielle

modifier

Les interfaces d'écoute définissant au moins deux méthodes possèdent une classe dont le nom est celui de l'interface où l'on remplace le suffixe Listener par Adapter. Cette classe définit des méthodes vides et permet aux applications de la surcharger pour ne définir que certaines méthodes de l'interface.

Exemple :

addWindowListener(new WindowAdapter()
{
	@Override
	public void windowClosing(WindowEvent e)
	{
		fermerFenetre();
	}
});