如何动态更改一个JFrame里面的JPanel?

问题描述 投票:39回答:14

说得简单,有一个简单的Java Swing应用程序,包括JFrame的,在它的一些组成部分。组分之一是,意在通过对用户操作的另一个的JPanel替换一个JPanel。

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

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

但是这将无法正常工作。您有什么建议?

java swing jpanel layout-manager cardlayout
14个回答
51
投票

您的使用情况下,似乎是完美的CardLayout

在卡片布局,您可以在同一时间在同一个地方添加多个面板,但随后显示或隐藏,一个面板。


1
投票

该layout.replace()答案只存在/工程对的GroupLayout管理器。

其他布局管理(CardLayout,BoxLayout的等),不支持此功能,但要求你先中的removeLayoutComponent(然后addLayoutComponent方法(回来了。:-) [只设置打抱不平]


0
投票

我建议你到两个面板的边框添加创建,然后通过调用调用setVisible两个(真/假)改变显示的面板。当调用调用setVisible,父母将被通报,并要求重绘自己。


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

}

有时候,你可以做的工作,而无需使用重新验证,有时甚至不使用repaint.My劝同时使用。


0
投票

只需设置ContentPane,(java 1.7,也许以上)这样以后调用该方法包():

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

frame.setContentPane(panel2);
frame.pack();
...

-1
投票

您可以使用替代的布局的方法:

layout.replace(existingComponent, newComponent)

现有的和新的组件可以JPanels了。


25
投票

1)设置第一面板:

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

2)更换面板:

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

另请注意,您必须在事件的线程做到这一点,以确保这一使用SwingUtilities.invokeLaterSwingWorker


18
投票
frame.setContentPane(newContents());
frame.revalidate(); // frame.pack() if you want to resize.

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

还要注意JFrame在可用性方面的名称非常混乱。添加组件或设置布局(通常)对所述内容窗格中的操作。奇怪的是,越来越布局确实给你的框架的布局管理器。


6
投票

希望这一段代码给你改变一个JFrame内jPanels的想法。

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

5
投票

在用户操作:

//你必须做的线沿线的东西

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

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

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


3
投票

这一切都取决于它如何去使用。如果你将要来回切换这两个板之间,然后使用CardLayout。如果你只从第一次切换到第二和(而不是回去),那么我会用telcontars建议,只需更换它。如果JPanel的是虽然不是在你的框架我唯一会改用的removeAll的remove(java.awt.Component)

如果你在某处这两种情况下它基本上是一个时间和空间之间的权衡。该CardLayout将节省您的时间,但由于必须保持这整个其他面板内存在任何时候都占用更多的内存。但是,在需要的时候,如果你只是更换面板和构建它的需求,你不必记住这meory左右,但它需要更多的时间来进行切换。

你也可以尝试JTabbedPane中使用的标签,而不是(它的,因为它处理显示出比CardLayout更容易/隐藏automitically)


1
投票

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


1
投票

问题:我已经把它添加到容器后,我的分量不会出现。

你需要添加一个组件后调用revalidaterepaint之前它会在你的容器出现。

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


1
投票

我有完全相同的问题! Increadible!我找到的解决方案是:

  1. 加入所有成分(JPanels)到容器上;
  2. 使用调用setVisible(假)方法对所有这些;
  3. 在用户操作,设置调用setVisible(真),以我想显示面板。
// 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);

没有重新验证(),没有的validate(),没有CardLayout需要。

© www.soinside.com 2019 - 2024. All rights reserved.