如何从 JFrame 中删除 JPanel?

Posted

技术标签:

【中文标题】如何从 JFrame 中删除 JPanel?【英文标题】:How can I remove a JPanel from a JFrame? 【发布时间】:2011-01-30 21:44:59 【问题描述】:

最近我在这里问how to add a new JPanel to JFrame。答案帮助我获得了工作代码。但我没有相关的问题:“如何删除旧的 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();
            
        );

    
;

【问题讨论】:

这似乎与您自己的问题重复:***.com/questions/2487658/… 【参考方案1】:

我在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()

【讨论】:

【参考方案2】:

罗曼,问题可以这样解决:

    run 方法的开头执行此操作:

final JPanel partnerSelectionPanel = generatePartnerSelectionPanel();

    然后这样做

frame.getContentPane().add(partnerSelectionPanel);

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

partnerSelectionPanel.setVisible(false);

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

【讨论】:

我认为使用 setVisible 是比添加和删除面板更好的解决方案。【参考方案3】:

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

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

【讨论】:

revalidate() 是我所需要的。谢谢。【参考方案4】:

从容器(框架)中移除组件(面板)的最简单方法是保留对它的引用,然后调用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();
        
        );


;

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

【讨论】:

谢谢!我测试了它并且它有效!它似乎比我的解决方案更好。与其隐藏,不如将其移除。 如果你还没有保存组件的链接,还有removeAll()方法。 很高兴帮助罗曼。如果它解决了您的问题,您可以单击答案旁边的勾号。是的,只要容器中没有任何其他组件,removeAll 就可以正常工作。 谢谢你的回答让我开心!顺便说一句,您也可以使用 this.revalidate(); 而不是 frame.invalidate(); frame.validate();

以上是关于如何从 JFrame 中删除 JPanel?的主要内容,如果未能解决你的问题,请参考以下文章

如何删除旧的 JPanel 并添加新的?

Java / Swing:从JPanel内部获取Window / JFrame

如何将两个 JPanel 添加到中心的 JFrame?

让 JButton 打开一个新的 JPanel

如何在 JFrame/JPanel 中可视化控制台 java

如何更改 JFrame 中 JPanel 的大小?