Ajout d'un JComponent dans un Jpanel

Fermé
Glxr - Modifié le 10 juil. 2022 à 11:17
 Glxr - 12 juil. 2022 à 12:28

Bonjour,

Je m’entraine à manipuler les frame/panel/component etc. avec Java, et j'ai donc commencé à créer une interface avec deux boutons Jouer et Quitter sur un panel. Lorsque l'on appuie sur Jouer, cela emmène sur un autre panel, appelé panel2 (peut-être pas la meilleure façon de faire pour changer d'affichage).

Sur ce panel2, je voulais ajouter un composant tel qu'un rectangle, tout simplement. Cependant, lorsque j'ajoute ce rectangle, il ne s'affiche rien, enfin juste le panel 2 et sa couleur (jaune).

Voici le code :

import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
import java.awt.event.*;

public class Main {

    private static JTextField text;

    public static void main(String[] args)  {
        InterfaceGraphique();
    }
    public static void InterfaceGraphique() {

        ///////////////// FRAME ///////////////////
        JFrame frame = new JFrame("Titre");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        ///////////////// PANEL ///////////////////
        JPanel panel = new JPanel();

        //Spécifie la couleur d'arrière-plan du JPanel
        panel.setBackground(Color.orange);
        panel.setOpaque(true);

        // Un titre
        panel.setBorder(BorderFactory.createTitledBorder("Titre panneau"));

        ///////////////// TEXTE ////////////////////

        text = new JTextField();
        text.setBounds(45,50,150,20);

        ///////////////// BOUTON ///////////////////

        JButton boutonJouer = new JButton("Jouer");
        JButton boutonQuitter = new JButton("Quitter");
        boutonJouer.setBounds(50,100,80,30);
        boutonQuitter.setBounds(100,100,80,30);
        boutonJouer.setBackground(Color.pink);
        boutonQuitter.setBackground(Color.red);

        // On enregistre une instance de la classe Main en tant qu'écouteur sur le bouton jouer
        boutonJouer.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                text.setText("test texte");
                JPanel panel2 = new JPanel();
                panel2.setBackground(Color.YELLOW);
                panel2.setOpaque(true);
              
                /////////////// Le problème se situe ici //////////////////////////

                panel2.add(new JComponent() {
                    public void paint(Graphics g) {

                        g.drawRect(50, 50, 350, 350);
                        g.setColor(Color.BLUE);
                    }
                });

                // Je redessine le panneau pour bien prendre en compte les modifications
                panel2.revalidate();
                panel2.repaint();

                frame.getContentPane().remove(panel);
                frame.add(panel2);
                frame.validate();
                frame.repaint();
                frame.setVisible(true);
            }
        });

        ///////////////// AFFICHAGE ///////////////////
        // On ajoute le panneau et les boutons à l'interface
        panel.add(boutonJouer);
        panel.add(boutonQuitter);
        frame.add(text);
        frame.add(panel);

        // configuration des dimensions de l'interface
        frame.setBounds(350,50,600,600);

        // on rend visible l'interface
        frame.setVisible(true);
    }
}

2 réponses

Finalement j'ai résolu mon problème en ajoutant :

this.setBounds(50, 50, 600, 600);

Dans la méthode paint de la classe anonyme.

Par contre, il y a encore quelque chose que je ne comprends pas avec cette même classe.

J'ai créé un tableau de caractères avec des "#" et je souhaite tracer un rectangle pour chaque # du tableau.

J'ai donc fait deux for each car le tableau est à deux dimensions : (je ne remets pas tout le code, j'ai uniquement ajouté le code ci-dessous à partir de la ligne 55)

                char[][] cadre = new char[][] {{'#','#','#','#','#','#','#','#','#',},
                                               {'#','#','#','#','#','#','#','#','#'},};

                for (char[] tab:cadre) { // parcours chaque élément tab pour le tableau cadre
                    for (char caractere: tab) { // parcours chaque caractère pour le tableau tab
                        if (caractere == '#') {

                            System.out.println("1 : " + x);
                            // Ajout composant rectangle
                            panel2.add(new JComponent() {

                                public void paint(Graphics g) {
                                    g.drawRect(x, y, 50, 50);
                                    g.setColor(Color.BLUE);

                                    // pour ajouter une taille du composant JComponent
                                    this.setBounds(50, 50, 600, 600);
                                    System.out.println("2 : " + x);
                                }
                            });
                            panel2.revalidate();
                            panel2.repaint();
                        }
                        x++;
                        y++;
                        System.out.println("3 : " + x);
                    }
                }

J'ai créé deux variables globales x et y (que j'ai défini plus haut dans la classe Main) initialisées à 0.

J'ai ajouté des sout pour pouvoir observer le comportement de x, et j'ai remarqué que la ligne

System.out.println("2 : " + x);

n'était exécuté qu'après les deux sout.

J'obtiens après exécution :

1 : 0
3 : 1
1 : 1
3 : 2
1 : 2
3 : 3
1 : 3
3 : 4
1 : 4
3 : 5
1 : 5
3 : 6
1 : 6
3 : 7
1 : 7
3 : 8
1 : 8
3 : 9
1 : 9
3 : 10
1 : 10
3 : 11
1 : 11
3 : 12
1 : 12
3 : 13
1 : 13
3 : 14
1 : 14
3 : 15
1 : 15
3 : 16
1 : 16
3 : 17
1 : 17
3 : 18
2 : 18
2 : 18
2 : 18
2 : 18
2 : 18
2 : 18
2 : 18
2 : 18
2 : 18
2 : 18
......

Alors là j'avoue ne vraiment pas comprendre, le if est bien exécuté, mais pas la classe qui est à intérieur de la boucle ...

0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
12 juil. 2022 à 11:49

Bonjour,

Lorsque le bouton "Jouer" est appuyé, cela déclenche un évènement et c'est l'Event Dispatch Thread qui le gère en appelant la méthode actionPerformed(ActionEvent e), mais l'EDT ne traite qu'un seul évènement à la fois, donc tant que l'évènement du bouton "Jouer" n'est pas terminé, avec les boucles for, les println("1 : " + x) et les println("3 : " + x), aucun autre évènement ne sera pris en compte.

Une fois que l'EDT a terminé de traiter ce premier évènement il peut commencer à en traiter un deuxième, c'est à ce moment là qu'il va pouvoir commencer à dessiner les nouveaux composants que tu as créé, avec les println("2 : " + x)

En partant de cette mécanique là, il faut reprendre toute la logique de ton programme, car tu ne peux pas imbriquer des évènements comme tu l'as fait. Il faudrait d'abord créer toute ton interface graphique, avec par exemple des boutons cachés que ton bouton "Jouer" ferait apparaître, mais qui existeraient déjà.

Remarque : Java FX remplace officiellement Swing pour les applications Desktop depuis la sortie de Java 8 en 2014, cela fait donc 8 ans qu'il n'y a plus aucune évolution de Swing, on le garde pour que les anciennes applications continuent de tourner, mais pour de nouvelles applications Java, il faudrait privilégier Java FX qui est la seule à bénéficier de fonctionnalités récentes et de mises à jours régulières.


0

Bonjour KX,

Merci pour ton aide, je n'avais pas réussi à trouver la solution sur internet.

Je comprends le problème, effectivement mon code est un peu bordélique car je fais plusieurs "tests" pour comprendre les mécaniques du Java. Cela ne me dérange donc pas du tout de tout refaire pour remettre en ordre, c'est d'ailleurs le but.

Ok pour les composants "cachés", mais j'avais pensé plutôt à mettre des conditions pour le bouton "Jouer", pour afficher le contenu lorsque l'EDT est terminé, enfin bon je vais réfléchir à tout cela.

Je ne savais pas non plus pour JavaFX, merci encore !

0