Adding JPanel from another class to JPanel in JFra

2020-02-26 09:14发布

问题:

I can't get my JFrame from main class to display JPanel from another class. Everything compiles without errors.

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);

    }

}

Is it good practice to keep diffrent JPanels in their own classes? (Example: Wanting to have JFrame contain few same size JPanels, which will be switched by setting setVisible() to true/false)

EDIT

Thank you for all your answers. Noted. Now back to my question:

Now that I know how to add single GUI elements created in other classes I want to know if it is possible to organize elements with layout manager in one of the classes (maybe in some other container than JPanel), so I can add them as a group organized in a layout (thats why I was asking about creating whole JPanel in other class). As on the picture:

JPanel (that 2nd class) code for this example would be:

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");

    }

}

I was thinking about navigating through the program GUI by setting JPanels (ones like in the example) to visible or not visible.

  1. Is it good way to do it?
  2. Should I split my GUI into few classes, or I should keep everything in one? I am asking, because now with only half of the GUI in the code its about 400 lines long (and it cant do anything than just "look" at this point). As I had said before - I am beginner and its one of the longest application I have written so far (which I am sure it is not that long anyway!).

EDIT

Maybe I am overthinking it, so in the end is it ok to have big GUI classes and to control visibility of different GUI areas by setting them visible or not?

EDIT

I've looked into the CardLayout tutorial at Oracle and it looks like it is good for my task (excluding the creating JPanels from the external classes, but it is ok). I misunderstood it at first and was thinking about CardLayout only in terms of tabbed pane (which I didn't want to implement in my project).

回答1:

First to answer your question, you need to add an instance of your panel to the frame with something like this in your JFrameTest constructor:

add(new JPanelOne());

You also need to add your button directly to JPanelOne itself:

public class JPanelOne extends JPanel {   

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

Second, I believe there is a problem with these lines of code:

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

    JPanel panelMain = new JPanel(mainLayout); 

Each container should have its own instance of a layout manager. Otherwise your GUI will do strange things:

setLayout(new FlowLayout());
JPanel panelMain = new JPanel(mainLayout);


回答2:

With some more help (user "Hilek" from some other site) I menaged to get the JPanel from another class to be displeyed in main class. Here is the 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);
        }
}

Print screen of working example:

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

Maybe someone will find it helpful in their problem.



回答3:

The problem comes from the JPanelOne class. It inherits JPanel but in the constructor, you create a new JPanel and then you add a button to it. If you do this instead:

public class JPanelOne extends JPanel {

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

it should work as you expect it.



回答4:

Don't call setSize() on your JFrame. Instead let the layouts set the proper sizes of their components and the GUI. After adding all components to your GUI, call pack() on the JFrame, then call setVisble(true). Note that most layouts respect a component's preferredSize more so than its size.

Also, your calling setVisible(true)on your individual components is unnecessary (unless you are changing their visibility after the GUI is up and running for some reason). You'll also want to read up more on using layout managers and will probably use FlowLayout less once you've studied them.

Edit
Regarding your recent Edit:

Maybe I am overthinking it, so in the end is it ok to have big GUI classes and to control visiblity of diffrent GUI areas by setting them visible or not?

I will answer that sometimes this is helpful, for instance if you want to change a standard calculator into a scientific calculator, sometimes it's good to simply show an already created JPanel filled with the advance calculation buttons by using setVisible(true). If on the other hand you want to swap "views" of your GUI to reflect a substantial change in its state, for instance a word processor changing from edit mode to print mode, you could swap JPanels easily to do this using a CardLayout.