CodeGym /Cours /JAVA 25 SELF /Événements dans Swing et AWT : bases, exemples

Événements dans Swing et AWT : bases, exemples

JAVA 25 SELF
Niveau 50, Leçon 1
Disponible

1. Introduction très brève à Swing et AWT

Si Java était une voiture, Swing et AWT en seraient le « tableau de bord » et le « volant ». AWT (Abstract Window Toolkit) est la toute première bibliothèque pour créer des applications de bureau en Java. Elle utilise les éléments d'interface « natifs » du système d'exploitation, donc l'apparence diffère sous Windows, Linux et Mac.

Swing est une surcouche plus moderne à AWT, entièrement écrite en Java. Swing est plus esthétique, plus flexible, prend en charge quantité de fonctionnalités supplémentaires et présente le même aspect sur toutes les plateformes (enfin, presque). Dans les deux cas, tous les éléments d'interface (boutons, champs de texte, cases à cocher, etc.) prennent en charge les événements.

Dans ce cours, nous utiliserons Swing : il est plus simple pour les débutants et plus fréquent dans les exemples pédagogiques. Voyons comment fonctionne le traitement des événements à travers la tâche la plus populaire — la réaction au clic sur un bouton.

Créer un bouton

Dans Swing, on crée un bouton ainsi :

JButton button = new JButton("Cliquez-moi !");

Ici, « Cliquez-moi ! » est le libellé du bouton.

Ajouter un écouteur

Pour réagir au clic, il faut « abonner » un écouteur à l'événement :

button.addActionListener(new MyActionListener());

Mais qui est ce MyActionListener ? C'est une classe qui implémente l'interface ActionListener :

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MyActionListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Le bouton a été cliqué !");
    }
}

Lorsque l'utilisateur clique sur le bouton, Swing appelle la méthode actionPerformed de tous les écouteurs enregistrés via addActionListener.

Exemple complet : une fenêtre simple avec un bouton

Rassemblons tout et créons une application fonctionnelle :

import javax.swing.*;
import java.awt.event.*;

public class SimpleButtonApp {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Exemple d'événement");
        JButton button = new JButton("Cliquez-moi !");

        // Ajoutons un écouteur au bouton
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Le bouton a été cliqué !");
                JOptionPane.showMessageDialog(frame, "Hourra ! Bouton cliqué !");
            }
        });

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(button);
        frame.setSize(300, 200);
        frame.setVisible(true);
    }
}

Ce qui se passe ici :

  • Nous créons une fenêtre (JFrame).
  • Nous créons un bouton (JButton).
  • Nous ajoutons un écouteur (classe anonyme pour éviter de multiplier les fichiers).
  • Dans actionPerformed, nous affichons un message dans la console et une boîte de dialogue (JOptionPane).
  • Nous ajoutons le bouton à la fenêtre et affichons la fenêtre à l'utilisateur.

Essayez vous-même de copier ce code, de l'exécuter — et de cliquer sur le bouton !

2. Classes anonymes et expressions lambda

Dans le code Java moderne, écrire des classes séparées pour un seul gestionnaire, c'est comme prendre un char pour aller acheter du pain. Il est bien plus pratique d'utiliser des classes anonymes ou des expressions lambda.

Classe anonyme

Nous avons déjà vu cette approche ci‑dessus :

button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // code de traitement
    }
});

Ici, la classe est déclarée sur place, sans nom.

Expression lambda (Java 8+)

Si l'interface de l'écouteur est fonctionnelle (c'est-à-dire qu'elle ne contient qu'une seule méthode abstraite), on peut utiliser une lambda :

button.addActionListener(e -> {
    System.out.println("Bouton cliqué via une lambda !");
});

Ou même plus court si le corps tient sur une seule ligne :

button.addActionListener(e -> System.out.println("Lambda : bouton cliqué !"));

Cela ne réduit pas seulement le code, cela le rend aussi plus lisible. Fait pour les curieux : l'interface ActionListener est fonctionnelle, car elle ne contient qu'une seule méthode, actionPerformed.

4. Autres types d'événements

Le monde ne se limite pas aux boutons ! Dans Swing et AWT, presque chaque élément d'interface prend en charge ses propres événements. Voici les plus populaires :

Événements de souris : MouseListener et MouseAdapter

Pour réagir aux clics de souris, utilisez MouseListener :

button.addMouseListener(new MouseListener() {
    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println("Clic de souris sur le bouton !");
    }
    // Les autres méthodes peuvent rester vides
    @Override public void mousePressed(MouseEvent e) {}
    @Override public void mouseReleased(MouseEvent e) {}
    @Override public void mouseEntered(MouseEvent e) {}
    @Override public void mouseExited(MouseEvent e) {}
});

Écrire cinq méthodes vides pour un seul gestionnaire n'est pas très pratique. Pour cela, il existe MouseAdapter :

button.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println("Clic de souris sur le bouton (via l'adaptateur) !");
    }
});

MouseAdapter implémente toutes les méthodes de l'interface, et vous ne redéfinissez que celles dont vous avez besoin.

Événements clavier : KeyListener/KeyAdapter

Pour intercepter les frappes :

button.addKeyListener(new KeyAdapter() {
    @Override
    public void keyPressed(KeyEvent e) {
        System.out.println("Touche enfoncée : " + e.getKeyChar());
    }
});

Événements de modification de texte : DocumentListener

Pour les champs de texte (JTextField, JTextArea) il existe des écouteurs spécifiques :

JTextField textField = new JTextField();
textField.getDocument().addDocumentListener(new DocumentListener() {
    @Override
    public void insertUpdate(DocumentEvent e) {
        System.out.println("Texte modifié : " + textField.getText());
    }
    @Override public void removeUpdate(DocumentEvent e) {}
    @Override public void changedUpdate(DocumentEvent e) {}
});

Au fait, pour la plupart des événements, il existe des adaptateurs afin d'éviter d'écrire des méthodes vides.

5. Pratique : mini-exemple avec une fenêtre et un bouton

Faisons une application GUI toute simple : une fenêtre avec un bouton qui, lorsqu'on clique dessus, incrémente un compteur et affiche un message.

Exemple : compteur de clics

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ClickCounterApp {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Compteur de clics");
        JButton button = new JButton("Cliquez-moi !");
        JLabel label = new JLabel("Clics : 0");
        // Compteur de clics (doit être final ou effectively final)
        final int[] count = {0};

        button.addActionListener(e -> {
            count[0]++;
            label.setText("Clics : " + count[0]);
        });

        frame.setLayout(new FlowLayout());
        frame.add(button);
        frame.add(label);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(250, 100);
        frame.setVisible(true);
    }
}

Explication :

  • Nous créons une fenêtre, un bouton et un label pour afficher le compteur.
  • Nous utilisons un tableau à un seul élément (final int[] count = {0};) pour contourner la contrainte des lambdas sur les variables final/effectivement final.
  • À chaque clic sur le bouton, nous incrémentons le compteur et mettons à jour le texte du label.

Idée pour s'exercer : essayez de changer la couleur du bouton à chaque cinquième clic !

6. Comment fonctionne le modèle événementiel en interne

Jetons un coup d'œil sous le capot pendant une minute. Lorsque vous appelez :

button.addActionListener(listener);

le bouton (objet JButton) ajoute votre écouteur à une liste interne. Quand l'utilisateur clique sur le bouton, il se passe ceci :

  1. Le bouton crée un objet événement (ActionEvent).
  2. Le bouton parcourt la liste des écouteurs et appelle chez chacun la méthode actionPerformed.
  3. Votre gestionnaire exécute les actions nécessaires (par exemple, met à jour le label).

Point essentiel à retenir : chaque événement peut avoir un nombre quelconque d'écouteurs — vous pouvez ajouter plusieurs gestionnaires pour un même bouton, ils seront appelés à la suite.

7. Schéma visuel : traitement d'un événement

graph TD
    A[L'utilisateur a cliqué sur le bouton] --> B{JButton}
    B --> C[Créer ActionEvent]
    C --> D[Appeler actionPerformed pour tous les écouteurs]
    D --> E[Le gestionnaire exécute les actions]

7. Erreurs typiques avec les événements dans Swing et AWT

Erreur n° 1 : vous avez oublié d'enregistrer l'écouteur. Le bouton ne réagit pas aux clics, car vous avez oublié d'appeler addActionListener.

Erreur n° 2 : travail lourd dans le gestionnaire. Si, dans votre gestionnaire d'événement, vous lancez une longue boucle ou téléchargez quelque chose sur Internet, l'interface va « geler ». Pour les tâches longues, utilisez des threads séparés ou SwingWorker.

Erreur n° 3 : tentative de modifier une variable depuis une lambda sans final/effectivement final. Dans une lambda, vous ne pouvez utiliser que des variables final ou « effectivement final ». Pour des compteurs, utilisez des tableaux ou des classes dédiées (AtomicInteger, si vous voulez faire ça proprement).

Erreur n° 4 : oubli de supprimer l'écouteur. Si vous supprimez un composant mais ne retirez pas l'écouteur, une fuite de mémoire est possible. Désabonnez les écouteurs quand le composant n'est plus nécessaire.

Erreur n° 5 : toutes les méthodes de l'interface ne sont pas implémentées. Si vous implémentez, par exemple, MouseListener directement, n'oubliez pas toutes les méthodes ! Mieux vaut utiliser des adaptateurs (MouseAdapter, KeyAdapter).

1
Mission
JAVA 25 SELF, niveau 50, leçon 1
Bloqué
Accueil dans la maison intelligente 🏡
Accueil dans la maison intelligente 🏡
1
Mission
JAVA 25 SELF, niveau 50, leçon 1
Bloqué
Activation du thermostat 🌡️
Activation du thermostat 🌡️
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION