【问题标题】:How to add components to JFrame once it's visible without having to resize it?一旦可见,如何将组件添加到 JFrame 而无需调整它的大小?
【发布时间】:2011-07-01 11:28:38
【问题描述】:

我有一个程序,其中有一个 JFrame 和一个 JButton。当用户点击JButton时,JFrame中的所有Components都会被移除,并添加一个红色背景的JPanel

当我单击JButton 时,红色的JPanel 不会变得可见,除非我调整JFrame 的大小(我使用的是Windows 7)。有没有办法实现我想要的,而无需手动调整 JFrame 的大小?

这是我正在使用的代码的一部分:

public class Demo implements ActionListener{
    public static void main(String args[]){
           ...............
        button.addActionListener(this); //'button' is an object of Jbutton class.
        frame.setVisible(true); //'frame' is an object of JFrame class.
        ............
    }

    public void actionPerformed(ActionEvent ae){
        frame.removeAllComponents();
        frame.add(panel1); //panel1 is an object of Jpanel class with red  background.

        /* Here is where my problem lies.
           panel1 is not visible to me unless I manually resize the JFrame. */
    }
}

【问题讨论】:

  • 在 panel1 构造函数中,你是在 jFrame 上调用 .pack() 吗?
  • 奇怪的是,我发现考虑到具体情况,这实际上更正确。
  • 考虑使用CardLayout。见E.G.

标签: java swing jframe jpanel resize


【解决方案1】:

要从JPaneltop-level containers 中删除(然后添加新的JComponents)JComponents,您只需调用一次并在操作结束时调用:

revalidate();
repaint();

如果您只调整或更改 JComponents:

validate();
repaint();

【讨论】:

  • repaint() 真的有必要吗?
  • @little bunny foo foo 为 LayoutManager 正确工作是的,例如 stackoverflow.com/questions/6390240/…
  • 你能看到我的帖子吗?我想听听你对我的发现的意见。 :)
  • 一直使用 revalidate() 即可。添加/删除和更改不需要区分,我看的方式是调用 revalidate() 是为了确保调用布局管理器并且更改组件的大小可能会影响布局。跨度>
  • 不可能在顶级容器上调用revalidate()。正如@Andrew Thompson 所建议的,我认为在这种情况下使用CardLayout 更合适。
【解决方案2】:

对我来说,这有点奇怪。事实证明,调用remove(Component comp),添加新的JPanel,然后调用pack() 对我有用。

public class Demo{

    public static void main(String[] args){
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run(){
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI(){
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JPanel panel = new JPanel();
        final JButton button = new JButton("Press Me");
        button.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e){
                frame.remove(panel);

                final JPanel redPanel = new JPanel(){

                    @Override
                    public Dimension getPreferredSize(){
                        return new Dimension(200, 200);
                    }

                    @Override
                    protected void paintComponent(Graphics g){
                        Graphics g2 = g.create();

                        g2.setColor(Color.RED);
                        g2.fillRect(0, 0, getWidth(), getHeight());

                        g2.dispose();
                    }
                };

                frame.add(redPanel);
                frame.pack();
            }
        });

        panel.add(button);
        frame.add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

按下按钮之前

按下按钮后

怪事

  1. 调用removeAll() 实际上导致GUI 冻结。看来此事件已发生before。即使在我尝试在删除所有组件之前删除动作侦听器之后,这种情况也会发生。
  2. 我不需要调用任何验证方法,甚至不需要重新绘制 GUI。

【讨论】:

  • 多次调用 pack() 从编程上讲根本不好,正如我在此处的帖子中所见:stackoverflow.com/questions/34604487/… Calling pack() 创建一个竞争条件,其中分配到内存并显示在屏幕上的组件不会像您想象的那样以线性顺序发生。如果您想删除某些内容,请使用 CardLayout 并包含两个窗格,一个带有某个组件,一个不包含某个组件,然后在需要时翻转到窗格。 你应该只调用一次 pack()。
【解决方案3】:

您必须在框架中强制执行 repaint(),因此框架必须自行重新绘制。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-10
    • 1970-01-01
    • 2012-07-19
    相关资源
    最近更新 更多