Java 如何从 JFrame 中删除 JPanel?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2501861/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 08:31:53  来源:igfitidea点击:

How can I remove a JPanel from a JFrame?

javauser-interfaceswingmultithreading

提问by Roman

Recently I asked here how to add a new JPanel to JFrame. The answer helped me to get a working code. But not I have a related question: "How can I remove an old JPanel". I need that because of the following problem.

最近我在这里问如何向 JFrame 添加新的 JPanel。答案帮助我获得了一个工作代码。但不是我有一个相关的问题:“如何删除旧的 JPanel”。由于以下问题,我需要它。

A new JPanel appears appears when I want (either time limit is exceeded or user press the "Submit" button). But in several seconds some element of the old JPanel appears together with the component of the new JPanel. I do not understand why it happens.

当我想要时会出现一个新的 JPanel(超过时间限制或用户按下“提交”按钮)。但是在几秒钟内,旧 JPanel 的某些元素与新 JPanel 的组件一起出现。我不明白为什么会这样。

I thought that it is because I have to other threads which update the window. But the first thread just add the old panel once (so, it should be finished). And in the second thread I have a loop which is broken (so, it also should be finished).

我认为这是因为我必须更新窗口的其他线程。但是第一个线程只添加了一次旧面板(因此,它应该完成)。在第二个线程中,我有一个循环被破坏(因此,它也应该完成)。

Here is my code:

这是我的代码:

private Thread controller = new Thread() {
    public void run() {
        // First we set the initial pane (for the selection of partner).
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                frame.getContentPane().add(generatePartnerSelectionPanel());
                frame.invalidate();
                frame.validate();
            }
        });
        // Update the pane for the selection of the parnter.
        for (int i=40; i>0; i=i-1) {
            final int sec = i;
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    timeLeftLabel.setText(sec + " seconds left.");
                }
            });
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) { }

            if (partnerSubmitted) {
                break;
            }
        }
        // For the given user the selection phase is finished (either the time is over or form was submitted).
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                frame.getContentPane().add(generateWaitForGamePanel());
                frame.invalidate();
                frame.validate();
            }
        });

    }
};

采纳答案by pstanton

the easiest way to remove a component (panel) from a container (frame) is to keep a reference to it, and then call Container.remove(Component)ie:

从容器(框架)中移除组件(面板)的最简单方法是保留对它的引用,然后调用Container.remove(Component)ie:

private Thread controller = new Thread() {
public void run() {

        final Component panel1 = generatePartnerSelectionPanel();

        // First we set the initial pane (for the selection of partner).
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                frame.getContentPane().add(panel1);
                frame.invalidate();
                frame.validate();
        }
        });
        // Update the pane for the selection of the parnter.
        for (int i=40; i>0; i=i-1) {
            final int sec = i;
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    timeLeftLabel.setText(sec + " seconds left.");
                }
            });
            try {Thread.sleep(1000);} catch (InterruptedException e) {}
            if (partnerSubmitted) {break;}
        }
        // For the given user the selection phase is finished (either the time is over or form was submitted).
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                frame.getContentPane().remove(panel1);
                frame.getContentPane().add(generateWaitForGamePanel());
                frame.invalidate();
                frame.validate();
        }
        });

}
};

i haven't tested this code but it should work.

我还没有测试过这段代码,但它应该可以工作。

回答by Roman

Roman, the problem can be solved like that:

Roman,这个问题可以这样解决:

  1. Do this in the beginning of your runmethod:
  1. run方法的开头执行此操作:

final JPanel partnerSelectionPanel = generatePartnerSelectionPanel();

final JPanel partnerSelectionPanel = generatePartnerSelectionPanel();

  1. Then do this
  1. 然后做这个

frame.getContentPane().add(partnerSelectionPanel);

frame.getContentPane().add(partnerSelectionPanel);

  1. Before you add the new panel do this:
  1. 在添加新面板之前,请执行以下操作:

partnerSelectionPanel.setVisible(false);

partnerSelectionPanel.setVisible(false);

It works. I do not know if it is a safe and/or elegant solution but it works.

有用。我不知道这是否是一个安全和/或优雅的解决方案,但它有效。

回答by camickr

Its the same whether you do add or remove a component on a visible GUI:

无论您在可见 GUI 上添加还是删除组件,都是一样的:

panel.remove(...);
panel.add(...);
panel.revalidate();
panel.repaint();

回答by M. Grieco

    panel.invalidate();
    panel.setVisible(false);
    panel.removeAll();
    frame.getContentPane().remove(panel);
    panel = null;

回答by alexander Mieremet

I had problems with requestFocusInWindowon TextFieldtoo. The trick is to not construct the components in the JPanelconstructor. But, make a build method and execute following code after it has been added to the frame.

我有问题requestFocusInWindowTextField了。诀窍是不要在构造函数中构造组件JPanel。但是,创建一个构建方法并在将其添加到框架后执行以下代码。

This worked for me:

这对我有用:

frame.getContentPane().removeAll(); //or .remove(previousPanel);
frame.getContentPane().add(newPanel);
panel.buildPanel(); // panel needs a builder method
frame.revalidate(); // in- and validate in one !! 
frame.pack(); // 

if you want to resize, you need preferredSize();on panel or use repaint()if you don't need to resize frame.

如果要调整大小,则需要preferredSize();在面板上或repaint()在不需要调整框架大小时使用。