1. Introduction aux événements
En programmation, un événement est un signal indiquant que quelque chose s’est produit. Il peut s’agir d’un clic sur un bouton, d’une saisie de texte, de la fin d’un chargement de données, de la modification d’une valeur de variable — tout ce qui peut survenir dans votre application et auquel vous, en tant que développeur, voulez réagir.
Par analogie, un événement est comme une sonnerie à la porte : quelqu’un est arrivé et vous décidez quoi faire ensuite. Vous pouvez ouvrir, ignorer, faire semblant de ne pas être là, ou même appeler toute la famille pour voir qui est venu. En programmation, l’événement est la « sonnerie », et votre réaction est le gestionnaire d’événement.
En Java, les événements sont le fondement de la programmation réactive et graphique (GUI). Sans eux, il n’y aurait ni boutons, ni listes déroulantes, ni applications de bureau, ni même de nombreux systèmes côté serveur.
Écouteur (Listener) : qu’est-ce que c’est et à quoi ça sert
Un écouteur (Listener) est un objet qui s’abonne à un événement donné et attend qu’il se produise. Dès que l’événement survient, l’écouteur reçoit un signal et exécute le code de réaction prévu.
En Java, les écouteurs sont généralement réalisés via des interfaces. L’un des exemples les plus courants est l’interface ActionListener. Elle est implémentée par les classes qui doivent réagir aux actions de l’utilisateur, par exemple un clic sur un bouton.
En pratique, l’interaction se construit ainsi : il y a une source d’événement, par exemple un bouton, et un écouteur — un objet qui implémente l’interface nécessaire. La source conserve la liste de tous les écouteurs qui y sont abonnés. Quand l’utilisateur clique sur le bouton, la source de l’événement appelle une méthode spéciale chez chacun des écouteurs.
Ce schéma ressemble à un abonnement aux actualités : tant que vous êtes abonné, vous recevez des notifications. Dans le cas de Java, cette notification est l’appel d’une méthode de l’écouteur, qui exécute des actions définies à l’avance.
2. Interfaces d’événements : ActionListener, MouseListener et autres
En Java, chaque type d’événement possède son interface d’écouteur :
| Type d’événement | Interface d’écouteur | Où utilisé |
|---|---|---|
| Action | |
Boutons, menus, minuteurs |
| Souris | |
Composants réagissant à la souris |
| Clavier | |
Champs de texte, n’importe quel composant |
| Changement | |
Curseurs, cases à cocher, modèles de données |
| Document | |
Modifications du texte (par exemple, JTextField) |
Chacune de ces interfaces définit une ou plusieurs méthodes à implémenter. Par exemple, ActionListener exige d’implémenter la méthode actionPerformed(ActionEvent e).
Exemple : ActionListener
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
class MyActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Le bouton a été cliqué !");
}
}
3. Principe de fonctionnement du modèle événementiel
Tout le modèle événementiel de Java repose sur un mécanisme simple mais puissant :
- La source d’événement (par exemple, un bouton) maintient une liste d’écouteurs.
- Lorsqu’une action se produit (par exemple, l’utilisateur clique sur le bouton), la source crée un objet d’événement (par exemple, ActionEvent).
- La source parcourt tous les écouteurs enregistrés et appelle chez eux la méthode correspondante (par exemple, actionPerformed), en passant l’objet d’événement.
- Chaque écouteur décide lui-même quoi faire de cet événement.
Schéma de fonctionnement des événements :
flowchart LR
A[L’utilisateur a cliqué sur le bouton] --> B[Le bouton a créé un événement]
B --> C[Le bouton appelle actionPerformed sur tous les écouteurs]
C --> D[L’écouteur réagit : exécute son propre code]
Exemple de code :
import javax.swing.*;
public class EventDemo {
public static void main(String[] args) {
JButton button = new JButton("Clique sur moi !");
button.addActionListener(new MyActionListener());
JFrame frame = new JFrame("Exemple d’événement");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(button);
frame.setSize(200, 100);
frame.setVisible(true);
}
}
Lorsque l’utilisateur clique sur le bouton, la méthode actionPerformed de tous les écouteurs se déclenche.
4. Exemple : ajout d’un écouteur à un bouton
Voyons le schéma classique sur un exemple simple.
Étape 1. Créer le bouton
JButton button = new JButton("Dire bonjour");
Étape 2. Créer l’écouteur
class HelloListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Bonjour, le monde !");
}
}
Étape 3. Enregistrer l’écouteur
button.addActionListener(new HelloListener());
En bref : à quoi cela ressemble en code
JButton button = new JButton("Dire bonjour");
button.addActionListener(new HelloListener());
5. Classes anonymes et expressions lambda : court et pratique
Classe anonyme
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Écouteur anonyme : bonjour !");
}
});
Expression lambda (Java 8+)
button.addActionListener(e -> System.out.println("Lambda ! Bonjour !"));
La lambda est la manière la plus concise d’ajouter un écouteur lorsque votre réaction à l’événement tient en une ou deux lignes.
6. Quel lien avec votre application ?
Intégrons ce mécanisme dans votre application d’apprentissage. Par exemple, nous avons une fenêtre simple avec un bouton « Ajouter une tâche ». Lorsqu’on clique sur le bouton, nous voulons ajouter une nouvelle tâche à la liste et afficher un message.
Exemple de code :
import javax.swing.*;
import java.awt.event.ActionListener;
public class TaskManagerGUI {
public static void main(String[] args) {
JFrame frame = new JFrame("Gestionnaire de tâches");
JButton addButton = new JButton("Ajouter une tâche");
// Nous utilisons une lambda comme écouteur
addButton.addActionListener(e -> {
System.out.println("Tâche ajoutée !");
// Ici, on pourrait ajouter la tâche à la liste
});
frame.add(addButton);
frame.setSize(300, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Désormais, votre application ne fait pas qu’exécuter des instructions, elle « réagit » aux actions de l’utilisateur !
7. Erreurs courantes lors du travail avec les écouteurs et les événements
Erreur n° 1 : vous avez oublié d’enregistrer l’écouteur. Si vous avez créé un écouteur mais ne l’avez pas ajouté à la source d’événement, votre code ne sera jamais appelé. C’est comme s’abonner à un magazine sans envoyer la demande — le magazine n’arrivera pas.
Erreur n° 2 : vous avez enregistré le même écouteur plusieurs fois. Si vous avez ajouté par inadvertance le même écouteur plusieurs fois, le gestionnaire sera appelé autant de fois que vous l’avez ajouté. Parfois cela peut être utile, mais le plus souvent c’est une source de bogues étranges (« pourquoi ma fonction se déclenche trois fois ?! »).
Erreur n° 3 : vous avez oublié de supprimer l’écouteur. Si l’écouteur n’est plus nécessaire mais que vous ne l’avez pas supprimé, il continue de rester en mémoire. Dans les applications de longue durée, cela peut entraîner des fuites de mémoire.
Erreur n° 4 : opérations longues dans le gestionnaire d’événement. Si vous effectuez un travail lourd directement dans le gestionnaire (par exemple, charger des données depuis Internet), l’interface « gèle » et l’utilisateur commence à s’impatienter. Il vaut mieux lancer le travail lourd dans un thread séparé.
Erreur n° 5 : exceptions non gérées dans l’écouteur. Si une exception survient dans votre gestionnaire, elle peut « tuer » toute la chaîne d’événements. Journalisez les erreurs et gérez les exceptions pour éviter que l’application ne plante.
GO TO FULL VERSION