How to add JPanel by clicking JButton?

前端 未结 2 1613
没有蜡笔的小新
没有蜡笔的小新 2020-11-29 08:39

I\'m trying to create a small GUI, it has 2 JButtons, and 2 JPanels with some drawing animation on each of them. By default it must show first JPanel, and by clicking on sec

相关标签:
2条回答
  • 2020-11-29 09:29

    I think you can just use CardLayout to implement your function. Please refer to here

    0 讨论(0)
  • 2020-11-29 09:39

    In order to reflect changes after adding/removing or resizing a component that is on a visible container call revalidate() and repaint() on the containers instance after adding/removing or resizing the component.

    Though this will not work in your code the main reason being inside JButton classes you recreate a new instance of MainPanel when in fact the 2 JButtons should share the single instance which is being used (you could pass MainPanel instance to the JButtons constructors, but you shouldn't really be extending a JButton unless adding custom functionality):

    class Button2 extends JButton {
        MainPanel someObj2 = new MainPanel();//you create an instance of MainPanel which isnt even showing and than do changes on that, this way you will never see any of the changes
    
        Button2() {
        }
    }
    

    A few other suggestions on your code:

    • Dont extend JButton class unnecessarily, simply create an instance of JButton like you did with JFrame and call methods on JButton instance.

    • Dont forget to create/manipulate Swing components on Event Dispatch Thread, via SwingUtilities.invokeLater(..) block, read here for more.

    Here is your code fixed (above suggestions ect implemented):

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class Test {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JFrame f = new JFrame();
    
                    final MainPanel myPanel = new MainPanel();
                    f.add(myPanel);
    
                    JButton button1 = new JButton("Show Animation A");
                    JButton button2 = new JButton("Show Animation B");
    
                    button1.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            myPanel.setI(1);
                            System.out.println("The variable i is now: " + myPanel.i);
                            myPanel.refreshMe();
                        }
                    });
                    button2.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            myPanel.setI(2);
                            System.out.println("The variable i is now: " + myPanel.i);
                            myPanel.refreshMe();
                        }
                    });
    
                    myPanel.add(button1);
                    myPanel.add(button2);
                    myPanel.checkPanel();
    
                    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
                    f.pack();
                    f.setVisible(true);
                }
            });
        }
    }
    
    class MainPanel extends JPanel {
    
        Panel1 p1 = new Panel1();
        Panel2 p2 = new Panel2();
        public int i = 1;  //this is being changed later by clicking JButton
        // I use this setter later in actionPerformed in order to change i
    
        public void setI(int i) {
            this.i = i;
        }
    
        public void refreshMe() {
            checkPanel();
    
            revalidate();
            repaint();
            // Need some help here:
            // I don't know what should I write, how to make a repaint of myPanel?
            System.out.println("just test, if the method refreshMe working by clicking some button");
        }
    
        public void checkPanel() {
            if (i == 1) {
                this.add(p1);
                this.remove(p2);//or it will remain there as this is default flowlayout
            } else if (i == 2) {
                this.add(p2);
                this.remove(p1);
            }
        }
    }
    
    class Panel1 extends JPanel {
    
        public Panel1() {
            this.setBackground(Color.BLUE);
            // a lot of drawing stuff going on here
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }
    }
    
    class Panel2 extends JPanel {
    
        public Panel2() {
            this.setBackground(Color.GREEN);
            // a lot of drawing stuff going on here
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }
    }
    

    However Id suggest something simpler, fortunately you have 2 choices:

    1) Use CardLayout which will allow you to flip between multiple components on a single JFrame/container.

    Here is an example I made:

    enter image description here

    import java.awt.BorderLayout;
    import java.awt.CardLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class Test {
    
        private final static String PANEL1 = "panel 1";
        private final static String PANEL2 = "panel 2";
    
        public Test() {
            initComponents();
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new Test();
                }
            });
        }
    
        private void initComponents() {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            JPanel panel1 = new JPanel();
            panel1.add(new JLabel("Panel 1"));
    
            JPanel panel2 = new JPanel();
            panel2.add(new JLabel("Panel 2"));
    
            //Create the panel that contains the "cards".
            final JPanel cards = new JPanel(new CardLayout());
            cards.add(panel1, PANEL1);
            cards.add(panel2, PANEL2);
    
            //create button to allow chnage to next card
            JButton buttonNext = new JButton(">");
            buttonNext.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent ae) {
                    CardLayout cl = (CardLayout) (cards.getLayout());//get cards
                    cl.next(cards);
                }
            });
    
            //create button to allow chnage to previous card
            JButton buttonPrev = new JButton("<");
            buttonPrev.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent ae) {
                    CardLayout cl = (CardLayout) (cards.getLayout());//get cards
                    cl.previous(cards);
                }
            });
    
            //create panel to hold buttons which will allow switching between cards
            JPanel buttonPanel = new JPanel();
            buttonPanel.add(buttonPrev);
            buttonPanel.add(buttonNext);
    
    
            frame.add(cards);
            frame.add(buttonPanel, BorderLayout.SOUTH);
    
            frame.pack();
            frame.setVisible(true);
        }
    }
    

    2) Use removeAll() technique i.e call frame.getContentPane().removeAll() which will remove all components currently on JFrame and than add the new content and call revalidate() and repaint() (also might want to add pack() in there) on JFrame instance to reflect changes. Though Id recommend CardLayout.

    0 讨论(0)
提交回复
热议问题