43

简单地说,有一个简单的 java swing 应用程序,它由 JFrame 和一些组件组成。其中一个组件是一个 JPanel,它旨在在用户操作时被另一个 JPanel 替换。

那么,做这种事情的正确方法是什么?我试过了

panel = new CustomJPanelWithComponentsOnIt();
parentFrameJPanelBelongsTo.pack();

但这行不通。你有什么建议?

4

14 回答 14

52

您的用例似乎非常适合CardLayout

在卡片布局中,您可以在同一位置添加多个面板,然后一次显示或隐藏一个面板。

于 2008-10-20T14:00:58.233 回答
28

1)设置第一个面板:

JFrame frame=new JFrame();
frame.getContentPane().add(new JPanel());

2)更换面板:

frame.getContentPane().removeAll();
frame.getContentPane().add(new JPanel());

另请注意,您必须在事件的线程中执行此操作,以确保使用SwingUtilities.invokeLaterSwingWorker

于 2008-10-20T13:10:03.343 回答
22
frame.setContentPane(newContents());
frame.revalidate(); // frame.pack() if you want to resize.

请记住,Java 使用“按值复制引用”参数传递。因此,更改变量不会更改传递给其他方法的引用副本。

另请注意JFrame,可用性的名称非常令人困惑。添加组件或设置布局(通常)在内容窗格上执行操作。奇怪的是,获取布局确实为您提供了框架的布局管理器。

于 2008-10-20T12:31:26.590 回答
7

希望这段代码能让您了解在 JFrame 中更改 jPanel。

public class PanelTest extends JFrame {

        Container contentPane;

        public PanelTest()  {
           super("Changing JPanel inside a JFrame");
           contentPane=getContentPane();
        }

        public void createChangePanel() {
           contentPane.removeAll();
           JPanel newPanel=new JPanel();
           contentPane.add(newPanel);
           System.out.println("new panel created");//for debugging purposes
           validate();
           setVisible(true);
        }
}
于 2009-05-22T05:16:23.143 回答
5

关于用户操作:

// 你必须按照以下方式做一些事情

myJFrame.getContentPane().removeAll()
myJFrame.getContentPane().invalidate()

myJFrame.getContentPane().add(newContentPanel)
myJFrame.getContentPane().revalidate()

然后您可以根据需要调整窗口大小。

于 2008-10-21T15:12:16.017 回答
3

这一切都取决于如何使用它。如果您想在这两个面板之间来回切换,请使用 CardLayout。如果您只是从第一个切换到第二个并且(而不是返回),那么我会使用telcontar的建议并替换它。虽然如果 JPanel 不是您框架中唯一的东西,我会使用 remove(java.awt.Component)而不是 removeAll。

如果您介于这两种情况之间,则基本上是时空权衡。CardLayout 将节省您的时间,但由于必须始终将整个其他面板保留在内存中而占用更多内存。但是,如果您只是在需要时更换面板并按需构建,则不必保留这些记忆,但切换需要更多时间。

您也可以尝试使用 JTabbedPane 来使用选项卡(它比 CardLayout 更容易,因为它会自动处理显示/隐藏)

于 2008-10-20T15:06:37.807 回答
1

其他人回答了这个问题。我想建议您使用 JTabbedPane 而不是替换内容。作为一般规则,让应用程序的视觉元素消失或被其他内容替换是不好的。当然,每条规则都有例外,只有您和您的用户社区才能决定最佳方法。

于 2008-10-20T13:11:19.893 回答
1

我遇到了完全相同的问题!不可思议!!我找到的解决方案是:

  1. 将所有组件(JPanels)添加到容器中;
  2. 对所有这些都使用 setVisible(false) 方法;
  3. 在用户操作时,将 setVisible(true) 设置为我想要显示的面板。
// Hiding all components (JPanels) added to a container (ex: another JPanel)
for (Component component : this.container.getComponents()) {
      component.setVisible(false);
}
// Showing only the selected JPanel, the one user wants to see
panel.setVisible(true);

不需要 revalidate(),不需要 validate(),不需要 CardLayout。

于 2011-05-20T07:47:56.717 回答
1

问题:我的组件添加到容器后没有出现。

添加组件后,您需要调用revalidaterepaint , 然后它才会显示在您的容器中。

来源:http ://docs.oracle.com/javase/tutorial/uiswing/layout/problems.html

于 2012-04-23T10:11:57.413 回答
1

layout.replace() 答案仅在 GroupLayout 管理器上存在/有效。

其他 LayoutManagers(CardLayout、BoxLayout 等)不支持此功能,但需要您先 RemoveLayoutComponent( 然后 AddLayoutComponent( 再次返回。:-) [只是设置记录]

于 2015-09-11T02:59:12.137 回答
1
Game game =  new Game();
getContentPane().removeAll(); 
setContentPane(game);  
getContentPane().revalidate(); //IMPORTANT
getContentPane().repaint();    //IMPORTANT
于 2021-06-30T15:31:48.503 回答
0

我建议您在创建框架时添加两个面板,然后通过在两者上调用 setVisible(true/false) 来更改可见面板。调用 setVisible 时,将通知父级并要求重新绘制自己。

于 2008-10-20T13:09:15.873 回答
0
class Frame1 extends javax.swing.JFrame {

    remove(previouspanel); //or getContentPane().removeAll();

    add(newpanel); //or setContentPane(newpanel);

    invalidate(); validate(); // or ((JComponent) getContentPane()).revalidate();

    repaint(); //DO NOT FORGET REPAINT

}

有时您可以在不使用重新验证的情况下完成工作,有时不使用重新绘制。我的建议是两者都使用。

于 2012-02-26T15:54:26.270 回答
0

只需在设置, ( ,可能更旧)之后调用方法pack() ,如下所示:ContentPanejava 1.7

JFrame frame = new JFrame();  
JPanel panel1 = new JPanel(); 
JPanel panel2 = new JPanel(); 
....
frame.setContentPane(panel1);
frame.pack();
...

frame.setContentPane(panel2);
frame.pack();
...
于 2012-08-09T04:27:00.923 回答