当前位置: 首页 > 知识库问答 >
问题:

如何通过点击JButton添加JPanel?

柯栋
2023-03-14

我试图创建一个小的GUI,它有2个JButtons和2个JPanels,每个JPanels上都有一些绘图动画。默认情况下,它必须显示第一个JPanel,通过单击第二个JButton我想看到第二个JPanel。所以:我创建了JFrame、Panel1和Panel2,在这里我绘制了我的动画,创建了Button1和Button2,并向它们添加了ActionListeners。我还有一个MainPanel,它有一个字段变量I。通过更改这个“I”,我的构造函数将Panel1(默认)或Panel2添加到MainPanel中(通过单击JButton2 I change I)。我把这个主面板加到我的框架上。所以我的问题是:在类MainPanel中我有refreshMehtml" target="_blank">方法,我应该在那里写什么来使我的GUI正常工作?多谢了。下面是我的代码:

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;

public class GuiTest {

    public static void main(String[] args) {
        JFrame f = new JFrame();
        MainPanel myPanel = new MainPanel();
        f.add(myPanel);
        Button1 button1 = new Button1();
        Button2 button2 = new Button2();
        myPanel.add(button1);
        myPanel.add(button2);
        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;
    }

    MainPanel() { 
        if (i == 1) {
            this.add(p1);
        }
        if (i == 2) {
            this.add(p2);
        }
    }

    public void refreshMe() {
        // 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");
    }
}

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

}

class Button1 extends JButton {
    MainPanel someObj1 = new MainPanel();

    Button1() {
        setText("Show Annimation A");
        addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                someObj1.setI(1);
                System.out.println("The variable i is now: " + someObj1.i);
                someObj1.refreshMe();

            }
        });
    }

}

class Button2 extends JButton {
    MainPanel someObj2 = new MainPanel();

    Button2() {
        setText("Show Annimation B");
        addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                someObj2.setI(2);
                System.out.println("The variable i is now: " + someObj2.i);
                someObj2.refreshMe();
            }
        });

    }

}

共有1个答案

章侯林
2023-03-14

为了反映添加/删除或调整可见容器上的组件后的更改,在添加/删除组件或调整组件的大小后,对容器实例调用revalidate()repaint()

虽然这在您的代码中不起作用,主要原因是在JButton类中,您重新创建了MainPanel的新实例,而实际上2个JButtons应该共享正在使用的单个实例(您可以将MainPanel实例传递给JButton的构造函数,但除非添加自定义功能,否则不应该真正扩展JButton):

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() {
    }
}

关于代码的其他一些建议:

>

  • 不要不必要地扩展JButton类,只需创建一个JButton实例,就像您对JFrame所做的那样,并调用JButton实例的方法。

    不要忘记通过SwingUtilities.invokelater(..)块在Event Dispatch Thread上创建/操作Swing组件,更多信息请阅读此处。

    这里是您的代码修复(上面的建议等执行):

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

    不过我建议一些更简单的方法,幸运的是你有两个选择:

    1)使用CardLayout,它将允许您在单个JFrame/容器上的多个组件之间翻转。

    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)使用RemoveAll()技术,即调用Frame.GetContentPane().RemoveAll(),这将删除JFrame上当前的所有组件,然后添加新内容,并调用Revalidate()Repaint()(也可能希望在其中添加Pack())实例以反映更改。尽管Id推荐CardLayout

  •  类似资料:
    • 如果你们能回答这个问题,我会印象深刻的。基本上,我正在开发一个全堆栈的web应用程序,它包含以下三个组件: MongoDB文章集 用Java 8编写的后端 Javascript前端 程序流程应如下所示: 用户打开网页将文本输入到指定标题、作者、流派和内容的表单中。 当他们单击“addItem”按钮时,它应该将数据序列化为原始JSON并将其发送到我的addItemendpoint。 然后数据被清理,

    • 问题内容: 按照标题,在Jenkins中,如何使用CLI将新的从属节点添加到构建集群中,或者如果没有CLI选项,是否可以使用另一种脚本化方法? 问题答案: 许多人使用Swarm插件来消除实际手动添加从站的需要。当然,您将需要编写swarm代理的安装脚本,但这应该很简单。

    • 我正在开发一个发票系统,我想在每次单击添加新按钮时创建新字段。 每次都需要在下面的代码中添加字段。 字段需要显示在其各自的列下。 下面是我设置的按钮: 我知道这个网站上一定有答案,但我似乎找不到。 请注意,我是Java开发新手

    • 问题内容: 我有个问题。我不知道如何通过单击JButton显示图像。 我有一个可以显示和隐藏图像的类: 我正在使用MVC,所以我想在我的控制器地图中使用JButton的代码,但是我不知道该怎么做。 单击按钮保持器时需要显示图像。 问题答案: 就像别人说的一样,总是用来显示图像。这样,很容易在需要时添加/删除它们,而不是绘画。此外,在您的代码中您正在重写,因为如果所讨论的组件具有一个,我们希望重写各

    • 当用户单击时,我想将不同的添加到我的。 面板必须根据用户单击的按钮进行更改。这是我的代码的一部分: 我该怎么解决这个问题?

    • 问题内容: 我是React的新手,对某种基本的东西感到困惑。 我需要在单击事件后呈现DOM之后将组件添加到DOM。 我最初的尝试如下,但是没有用。但这是我想尝试的最好的方法。(预先为将jQuery与React混合使用而道歉。) 希望我已经清楚需要做什么,希望您能帮助我获得适当的解决方案。 问题答案: 正如@Alex McMillan所提到的那样,使用state来指示应在dom中呈现的内容。 在下面