TD01 : Gestion des composants et héritage

Partie 1 : Création et Interaction (Questions 1, 2 et 3)

Détail des modifications apportées au programme initial :

  1. Question 1 (Couleur aléatoire) : Le programme initial affichait une couleur fixe. Nous avons modifié le constructeur pour utiliser la fonction Math.random(). Cette fonction renvoie un nombre décimal entre 0.0 et 1.0. En le multipliant par 256 et en le convertissant en entier (int), nous obtenons une valeur entre 0 et 255 pour définir les composantes Rouge, Vert et Bleu de la couleur.
  2. Question 2 (Ajout du bouton) : Nous avons déclaré un objet JButton nommé monBouton. Nous l'avons instancié avec le texte "Changer couleur" et ajouté à la fenêtre avec la méthode add(). Grâce au FlowLayout, il se place automatiquement à la suite du label.
  3. Question 3 (Interaction) : Pour rendre le bouton actif, la classe implémente désormais l'interface ActionListener. Nous avons abonné la fenêtre aux événements du bouton via monBouton.addActionListener(this). Enfin, nous avons écrit la méthode actionPerformed qui détecte le clic, affiche un message en console et recalcule une couleur de fond aléatoire.
Capture d'écran Fenetre.java
Fig 1. Résultat final de la Partie 1 : Fenêtre avec couleur aléatoire et bouton fonctionnel.

Code Source Complet : Fenetre.java

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

// La classe implémente ActionListener pour pouvoir écouter les clics (Question 3)
public class Fenetre extends JFrame implements ActionListener {

    JLabel monLabel;
    JButton monBouton; // Déclaration du bouton (Question 2)

    public Fenetre() {
        super("Fenêtre de composants");

        // --- Question 1 : Tirage au sort de la couleur ---
        // Math.random() donne un double entre 0.0 et 1.0
        // On multiplie par 256 et on caste en (int) pour avoir 0..255
        int r = (int)(Math.random() * 256);
        int v = (int)(Math.random() * 256);
        int b = (int)(Math.random() * 256);
        
        // Application de la couleur au fond de la fenêtre
        getContentPane().setBackground(new Color(r, v, b));

        // Paramétrage de la fenêtre
        setSize(350, 250);
        setLayout(new FlowLayout());

        monLabel = new JLabel("Mon composant :", SwingConstants.CENTER);
        monLabel.setFont(new Font("Arial", Font.BOLD, 20));
        add(monLabel);

        // --- Question 2 : Ajout du bouton ---
        monBouton = new JButton("Changer couleur");
        
        // --- Question 3 : Rendre le bouton actif ---
        // "this" désigne la fenêtre elle-même, qui contient la méthode actionPerformed
        monBouton.addActionListener(this);
        
        add(monBouton);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    // --- Question 3 : Méthode de gestion des événements ---
    public void actionPerformed(ActionEvent e) {
        // Vérification que l'événement vient bien de notre bouton
        if (e.getSource() == monBouton) {
            System.out.println("Clic sur le bouton.");
            
            // On recalcule une couleur aléatoire
            int r = (int)(Math.random() * 256);
            int v = (int)(Math.random() * 256);
            int b = (int)(Math.random() * 256);
            
            // On change la couleur de fond
            getContentPane().setBackground(new Color(r, v, b));
            
            // On demande à la fenêtre de se redessiner
            repaint();
        }
    }

    public static void main(String a[]) {
        new Fenetre();
    }
}

Partie 2 : Modularité et Instances Multiples (Questions 4 et 5)

Objectif : Structurer le programme en composants réutilisables.

Conformément aux consignes, nous avons séparé le code en deux classes distinctes (dans deux fichiers différents) :

À la question 5, nous chargeons trois instances de Panneau. Grâce à l'utilisation du mot-clé new, chaque panneau est un objet indépendant en mémoire, possédant ses propres variables de couleur.

Capture Lancement
Fig 2. Lancement du programme : 3 panneaux indépendants avec des couleurs différentes.
Capture Clic Milieu
Fig 3. Après un clic sur le bouton du milieu : seul le panneau concerné change de couleur.

Fichier 1 : Panneau.java

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

// Cette classe correspond à un module "Label + Bouton + Couleur" autonome
public class Panneau extends JPanel implements ActionListener {
    
    JLabel monLabel;
    JButton monBouton;

    public Panneau() {
        // Initialisation de la couleur propre à CETTE instance de panneau
        int r = (int)(Math.random() * 256);
        int v = (int)(Math.random() * 256);
        int b = (int)(Math.random() * 256);
        
        // "this" fait référence au panneau lui-même
        this.setBackground(new Color(r, v, b));

        monLabel = new JLabel("Mon composant : ");
        monLabel.setFont(new Font("Arial", Font.BOLD, 20));
        add(monLabel);

        monBouton = new JButton("Clic sur moi");
        // Le panneau s'écoute lui-même pour gérer le clic sur son bouton
        monBouton.addActionListener(this);
        add(monBouton);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == monBouton) {
            // Changement de couleur uniquement pour ce panneau
            int r = (int)(Math.random() * 256);
            int v = (int)(Math.random() * 256);
            int b = (int)(Math.random() * 256);
            
            this.setBackground(new Color(r, v, b));
            repaint();
        }
    }
}

Fichier 2 : ChargePanneau.java

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

public class ChargePanneau extends JFrame {
    
    public ChargePanneau() {
        super("Fenêtre de composants");
        // On agrandit la fenêtre pour bien voir les 3 panneaux
        setSize(400, 450);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        // Utilisation d'un GridLayout (3 lignes, 1 colonne) pour empiler les composants
        setLayout(new GridLayout(3, 1));
        
        // Création et ajout de 3 objets Panneau distincts
        add(new Panneau());
        add(new Panneau());
        add(new Panneau());
        
        setVisible(true);
    }

    public static void main(String args[]) {
        // Lancement de la fenêtre principale
        new ChargePanneau();
    }
}

Partie 3 : Question Théorique (Question 6)

Question : Si vous utilisez le mot-clé static dans la définition de la variable « couleur » de la classe Panneau, que se passe-t-il et pourquoi ?

Réponse :

Si on déclare la variable couleur avec le mot-clé static (exemple : static Color couleur;), elle cesse d'être une variable d'instance (propre à chaque objet) pour devenir une variable de classe.

Conséquences :