如何从JFrame中移除一个JPanel?

12

最近我在这里询问 如何向JFrame添加新的JPanel。答案帮助我得到了可工作的代码。但现在我有一个相关问题:“如何删除旧的JPanel”。我需要这样做是因为以下问题。

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

我认为这是因为我有其他更新窗口的线程。但第一个线程只添加旧面板一次(所以它应该完成)。而在第二个线程中,我有一个被打断的循环(所以它也应该完成)。

这是我的代码:

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

    }
};

这似乎是您自己的问题的重复:https://dev59.com/HUzSa4cB1Zd3GeqPo7Q5#2487771 - Russ Hayward
4个回答

10

在可见的GUI上添加或删除组件都是相同的:

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

revalidate() 是我所需要的。谢谢。 - cbaldan

9

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

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

}
};

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

谢谢!我测试了一下,它可以正常工作!看起来比我的解决方案更好。最好是删除它而不是隐藏它。 - Roman
如果您没有保存组件的链接,也可以使用removeAll()方法。 - Ha.
很高兴能帮助Roman。如果它解决了你的问题,你可以点击答案旁边的勾号。而且,如果容器中没有其他组件,removeAll 将可以正常工作。 - pstanton
谢谢,伙计!你的回答让我开心了一整天!另外,你也可以使用 this.revalidate(); 来代替 frame.invalidate(); frame.validate(); - Mohamed Khamis

2

我也遇到了在TextField上使用requestFocusInWindow时的问题。诀窍在于不要在JPanel构造函数中构建组件。相反,创建一个构建方法,在将面板添加到框架后执行以下代码。

这对我有用:

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

如果你想要调整大小,需要在面板上使用 preferredSize(); 或者如果不需要更改窗口大小可以使用 repaint()


0
Roman,这个问题可以这样解决:
  1. 在你的 run 方法的开头添加以下代码:

final JPanel partnerSelectionPanel = generatePartnerSelectionPanel();

  1. 然后做以下操作:

frame.getContentPane().add(partnerSelectionPanel);

在添加新面板之前,请执行以下操作:

partnerSelectionPanel.setVisible(false);

它能够工作。我不知道它是否是一个安全和/或优雅的解决方案,但它能够工作。


我认为使用setVisible比添加和删除面板是更好的解决方案。 - Jason

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接