web-dev-qa-db-fra.com

Ajout de JPanel d'une autre classe à JPanel dans JFrame

Je ne peux pas obtenir mon JFrame de la classe principale pour afficher JPanel d'une autre classe. Tout se compile sans erreurs.

JFrameTest.Java:

package jframetest;

import Java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class JFrameTest extends JFrame {

    public JFrameTest() {

        FlowLayout mainLayout = new FlowLayout();
        setSize(320, 480);
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(mainLayout);

        JPanel panelMain = new JPanel(mainLayout);

        JButton testButton = new JButton("Test12");
        panelMain.add(testButton);

        JPanelOne panel = new JPanelOne();
        panelMain.add(panel);
        panel.setVisible(true);
        add(panelMain);



    }

    public static void main(String[] arguments) {

        JFrameTest frame = new JFrameTest();
        frame.setVisible(true);


    }
}

JPanelOne.Java:

package jframetest;

import Java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JPanel;


public class JPanelOne extends JPanel {

    public JPanelOne() {

        FlowLayout layoutPanel = new FlowLayout();
        JPanel panel = new JPanel(layoutPanel);
        JButton button = new JButton("test");
        panel.add(button);
        panel.setVisible(true);

    }

}

Est-ce une bonne pratique de garder différents JPanels dans leurs propres classes? (Exemple: vous voulez que JFrame contienne quelques JPanels de même taille, qui seront commutés en définissant setVisible () sur true/false)

MODIFIER

Merci pour toutes vos réponses. C'est noté. Revenons maintenant à ma question:

Maintenant que je sais comment ajouter des éléments GUI uniques créés dans d'autres classes, je veux savoir s'il est possible d'organiser des éléments avec le gestionnaire de disposition dans l'une des classes (peut-être dans un autre conteneur que JPanel), afin que je puisse les ajouter en tant que groupe organisé dans une mise en page (c'est pourquoi je demandais de créer JPanel entier dans une autre classe). Comme sur la photo:

Le code JPanel (cette 2e classe) pour cet exemple serait:

package jframetest;

import Java.awt.*;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import net.miginfocom.swing.MigLayout;


public class JPanelOne extends JPanel {

    private JPanel panelSettingsMain;
    private JLabel labelChooseLanguage, labelWordsCollection;
    private JButton buttonSelectLanguage, buttonSelectCollection,
            buttonStatistics, buttonPrintingOptions, buttonAddNewWordCollection,
            buttonInterfaceCustomization;
    private JSeparator separatorSettingsOne, separatorSettingsTwo,
            separatorSettingsThree, separatorSettingsFour,
            separatorSettingsFive;
    private Color greenRegular, separatorGreenLight, separatorGreenDark;

    public JPanelOne() {

        // creating settings main panel

        // setting up layout managers
        MigLayout layoutSettingsMain = new MigLayout(
                "insets 3 0 0 0");

        // setting up colors
        greenRegular = new Color(30, 165, 145);
        separatorGreenLight = new Color(190, 240, 220);
        separatorGreenDark = new Color(130, 205, 180);

        panelSettingsMain = new JPanel(layoutSettingsMain);
        panelSettingsMain.setBackground(Color.WHITE);

            // setting up choose language label
            labelChooseLanguage = new JLabel("Choose language:");
            panelSettingsMain.add(labelChooseLanguage,
                    "gapleft 10, gaptop 15, width 200");

            // setting up select language button
            buttonSelectLanguage = new JButton("language");
            buttonSelectLanguage.setForeground(greenRegular);
            buttonSelectLanguage.setFocusPainted(false);
            buttonSelectLanguage.setBorder(null);
            buttonSelectLanguage.setContentAreaFilled(false);
            buttonSelectLanguage.setCursor(new Java.awt.Cursor(
                    Java.awt.Cursor.HAND_CURSOR));
            panelSettingsMain.add(buttonSelectLanguage, "gapbottom 15px, wrap");

            // setting up light separator
            separatorSettingsOne = new JSeparator();
            separatorSettingsOne.setForeground(separatorGreenLight);
            panelSettingsMain.add(separatorSettingsOne,
                    "span 2, width 320, gapbottom 15, wrap");

            // setting up words collection label
            labelWordsCollection = new JLabel("Words collection:");
            panelSettingsMain.add(labelWordsCollection, "gapleft 10");

            // setting up selectcollection button
            buttonSelectCollection = new JButton("collection");
            buttonSelectCollection.setForeground(greenRegular);
            buttonSelectCollection.setFocusPainted(false);
            buttonSelectCollection.setBorder(null);
            buttonSelectCollection.setContentAreaFilled(false);
            buttonSelectCollection.setCursor(new Java.awt.Cursor(
                    Java.awt.Cursor.HAND_CURSOR));
            panelSettingsMain.add(buttonSelectCollection,
                    "gapbottom 15px, wrap");

            // setting up dark separator
            separatorSettingsTwo = new JSeparator();
            separatorSettingsTwo.setForeground(separatorGreenDark);
            panelSettingsMain.add(separatorSettingsTwo,
                    "span 2, width 320, gapbottom 15px, wrap");

            // setting up show statistics button
            buttonStatistics = new JButton("Show statistics");
            buttonStatistics.setForeground(greenRegular);
            buttonStatistics.setFocusPainted(false);
            buttonStatistics.setBorder(null);
            buttonStatistics.setContentAreaFilled(false);
            buttonStatistics.setCursor(new Java.awt.Cursor(
                    Java.awt.Cursor.HAND_CURSOR));
            panelSettingsMain.add(buttonStatistics,
                    "gapleft 10, gapbottom 15px, , wrap");

            // setting up dark separator
            separatorSettingsThree = new JSeparator();
            separatorSettingsThree.setForeground(separatorGreenDark);
            panelSettingsMain.add(separatorSettingsThree,
                    "span 2, width 320, gapbottom 15px, wrap");

            // setting up printing options button
            buttonPrintingOptions = new JButton("Printing options");
            buttonPrintingOptions.setForeground(greenRegular);
            buttonPrintingOptions.setFocusPainted(false);
            buttonPrintingOptions.setBorder(null);
            buttonPrintingOptions.setContentAreaFilled(false);
            buttonPrintingOptions.setCursor(new Java.awt.Cursor(
                    Java.awt.Cursor.HAND_CURSOR));
            panelSettingsMain.add(buttonPrintingOptions,
                    "gapleft 10, gapbottom 15px, wrap");

            // setting up dark separator
            separatorSettingsFour = new JSeparator();
            separatorSettingsFour.setForeground(separatorGreenDark);
            panelSettingsMain.add(separatorSettingsFour,
                    "span 2, width 320, gapbottom 15px, wrap");

            // setting up add new Word collection button
            buttonAddNewWordCollection = new JButton("Add new Word collection");
            buttonAddNewWordCollection.setForeground(greenRegular);
            buttonAddNewWordCollection.setFocusPainted(false);
            buttonAddNewWordCollection.setBorder(null);
            buttonAddNewWordCollection.setContentAreaFilled(false);
            buttonAddNewWordCollection.setCursor(new Java.awt.Cursor(
                    Java.awt.Cursor.HAND_CURSOR));
            panelSettingsMain.add(buttonAddNewWordCollection,
                    "gapleft 10, gapbottom 15px, , wrap");

            // setting up dark separator
            separatorSettingsFive = new JSeparator();
            separatorSettingsFive.setForeground(separatorGreenDark);
            panelSettingsMain.add(separatorSettingsFive,
                    "span 2, width 320, gapbottom 10px, wrap");

            // setting up interface customization button
            buttonInterfaceCustomization = new JButton(
                    "Interface customization");
            buttonInterfaceCustomization.setForeground(greenRegular);
            buttonInterfaceCustomization.setFocusPainted(false);
            buttonInterfaceCustomization.setBorder(null);
            buttonInterfaceCustomization.setContentAreaFilled(false);
            buttonInterfaceCustomization.setCursor(new Java.awt.Cursor(
                    Java.awt.Cursor.HAND_CURSOR));
            panelSettingsMain.add(buttonInterfaceCustomization,
                    "gapleft 10, gapbottom 15px, wrap");

    }

}

Je pensais naviguer dans l'interface graphique du programme en définissant JPanels (comme dans l'exemple) sur visible ou non visible.

  1. Est-ce une bonne façon de le faire?
  2. Dois-je diviser mon interface graphique en quelques classes, ou dois-je tout garder en une? Je pose la question, car maintenant avec seulement la moitié de l'interface graphique dans le code, c'est environ 400 lignes de long (et il ne peut rien faire que simplement "regarder" à ce stade). Comme je l'ai déjà dit - je suis débutant et c'est l'une des applications les plus longues que j'ai écrites jusqu'à présent (ce qui, je suis sûr, n'est pas si long de toute façon!).

MODIFIER

Peut-être que je réfléchis trop, donc à la fin est-il acceptable d'avoir de grandes classes d'interface graphique et de contrôler la visibilité de différentes zones d'interface graphique en les définissant comme visibles ou non?

MODIFIER

J'ai regardé dans le didacticiel CardLayout chez Oracle et il semble que c'est bon pour ma tâche (en excluant la création de JPanels des classes externes, mais ça va). Je l'ai mal compris au début et je ne pensais à CardLayout qu'en termes de volet à onglets (que je ne voulais pas implémenter dans mon projet).

9
TV.

Avec un peu plus d'aide (utilisateur "Hilek" d'un autre site), j'ai réussi à obtenir le JPanel d'une autre classe à afficher dans la classe principale. Voici le code:

JFrameTest.Java:

import Java.awt.Color;
import Java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class JFrameTest extends JFrame {

        private JButton testButton;
        private JPanel panelMain;
        private JPanelOne panel;

        public JFrameTest() {

                // setting up JFrame
                setLayout(null);
                setPreferredSize(new Dimension(420, 90));
                setResizable(false);
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                // creating main JPanel (white)
                panelMain = new JPanel();
                panelMain.setBackground(Color.WHITE);
                panelMain.setBounds(0, 0, 420, 90);
                panelMain.setPreferredSize(new Dimension(200, 40));
                add(panelMain);

                // creating JButton in the main JPanel (white)
                testButton = new JButton("Button from main class");
                panelMain.add(testButton);

                // creating new JPanelOne object from JPanelOne class containing black JPanel
                panel = new JPanelOne();

                // adding black JPanel to main JPanel (white)
                panelMain.add(panel);

                pack();

        }

        public static void main(String[] arguments) {

                // creating JFrame object and setting it visible
                JFrameTest frame = new JFrameTest();
                frame.setVisible(true);

        }

}

JPanelOne.Java:

import Java.awt.Color;
import Java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

public class JPanelOne extends JPanel
{

        public JPanelOne()
        {
                // setting up black JPanel
                JPanel panel = new JPanel();
                panel.setPreferredSize(new Dimension(220, 40));
                panel.setBackground(Color.BLACK);

                // creating button on external JPanel
                JButton button = new JButton("Button (+JPanel) from external class");

                // adding button to the black JPanel
                panel.add(button);

                // adding blackJPanel
                add(panel);
        }
}

Imprimer l'écran de l'exemple de travail:

http://i.stack.imgur.com/qKeBp.jpg

Peut-être que quelqu'un trouvera cela utile dans son problème.

5
TV.

Tout d'abord, pour répondre à votre question, vous devez ajouter une instance de votre panneau au cadre avec quelque chose comme ceci dans votre constructeur JFrameTest:

add(new JPanelOne());

Vous devez également ajouter votre bouton directement à JPanelOne lui-même:

public class JPanelOne extends JPanel {   

  public JPanelOne() {   
    JButton button = new JButton("test");   
    add(button);   
  }   
}

Deuxièmement, je pense qu'il y a un problème avec ces lignes de code:

    FlowLayout mainLayout = new FlowLayout(); 
    // snip...
    setLayout(mainLayout); 

    JPanel panelMain = new JPanel(mainLayout); 

Chaque conteneur doit avoir sa propre instance d'un gestionnaire de disposition. Sinon, votre GUI fera des choses étranges:

setLayout(new FlowLayout());
JPanel panelMain = new JPanel(mainLayout);
6
Code-Apprentice

N'appelez pas setSize() sur votre JFrame. Au lieu de cela, laissez les mises en page définir les tailles appropriées de leurs composants et de l'interface graphique. Après avoir ajouté tous les composants à votre GUI, appelez pack() sur le JFrame, puis appelez setVisble(true). Notez que la plupart des mises en page respectent davantage la taille préférée d'un composant que sa taille.

En outre, votre appel setVisible(true) sur vos composants individuels est inutile (à moins que vous ne changiez leur visibilité après que l'interface graphique soit opérationnelle pour une raison quelconque). Vous voudrez également en savoir plus sur l'utilisation des gestionnaires de mise en page et vous utiliserez probablement moins FlowLayout une fois que vous les aurez étudiés.

Modifier
Concernant votre dernière modification:

Peut-être que je réfléchis trop, donc à la fin est-il acceptable d'avoir de grandes classes d'interface graphique et de contrôler la visibilité de différentes zones d'interface graphique en les définissant comme visibles ou non?

Je répondrai que parfois cela est utile, par exemple si vous voulez changer une calculatrice standard en calculatrice scientifique, parfois il est bon d'afficher simplement un JPanel déjà créé rempli des boutons de calcul avancé en utilisant setVisible (true). Si d'un autre côté vous voulez permuter les "vues" de votre GUI pour refléter un changement substantiel dans son état, par exemple un traitement de texte passant du mode d'édition au mode d'impression, vous pouvez échanger facilement JPanels pour le faire en utilisant un CardLayout.

4

Le problème vient de la classe JPanelOne. Il hérite de JPanel mais dans le constructeur, vous créez un nouveau JPanel puis vous y ajoutez un bouton. Si vous faites cela à la place:

public class JPanelOne extends JPanel {

   public JPanelOne() {
       JButton button = new JButton("test");
       add(button);
   }
}

cela devrait fonctionner comme vous l'attendez.

4
aymeric