简单地说,有一个简单的 java swing 应用程序,它由 JFrame 和一些组件组成。其中一个组件是一个 JPanel,它旨在在用户操作时被另一个 JPanel 替换。
那么,做这种事情的正确方法是什么?我试过了
panel = new CustomJPanelWithComponentsOnIt();
parentFrameJPanelBelongsTo.pack();
但这行不通。你有什么建议?
简单地说,有一个简单的 java swing 应用程序,它由 JFrame 和一些组件组成。其中一个组件是一个 JPanel,它旨在在用户操作时被另一个 JPanel 替换。
那么,做这种事情的正确方法是什么?我试过了
panel = new CustomJPanelWithComponentsOnIt();
parentFrameJPanelBelongsTo.pack();
但这行不通。你有什么建议?
您的用例似乎非常适合CardLayout。
在卡片布局中,您可以在同一位置添加多个面板,然后一次显示或隐藏一个面板。
1)设置第一个面板:
JFrame frame=new JFrame();
frame.getContentPane().add(new JPanel());
2)更换面板:
frame.getContentPane().removeAll();
frame.getContentPane().add(new JPanel());
另请注意,您必须在事件的线程中执行此操作,以确保使用SwingUtilities.invokeLater或SwingWorker
frame.setContentPane(newContents());
frame.revalidate(); // frame.pack() if you want to resize.
请记住,Java 使用“按值复制引用”参数传递。因此,更改变量不会更改传递给其他方法的引用副本。
另请注意JFrame
,可用性的名称非常令人困惑。添加组件或设置布局(通常)在内容窗格上执行操作。奇怪的是,获取布局确实为您提供了框架的布局管理器。
希望这段代码能让您了解在 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);
}
}
关于用户操作:
// 你必须按照以下方式做一些事情
myJFrame.getContentPane().removeAll()
myJFrame.getContentPane().invalidate()
myJFrame.getContentPane().add(newContentPanel)
myJFrame.getContentPane().revalidate()
然后您可以根据需要调整窗口大小。
这一切都取决于如何使用它。如果您想在这两个面板之间来回切换,请使用 CardLayout。如果您只是从第一个切换到第二个并且(而不是返回),那么我会使用telcontar的建议并替换它。虽然如果 JPanel 不是您框架中唯一的东西,我会使用 remove(java.awt.Component)而不是 removeAll。
如果您介于这两种情况之间,则基本上是时空权衡。CardLayout 将节省您的时间,但由于必须始终将整个其他面板保留在内存中而占用更多内存。但是,如果您只是在需要时更换面板并按需构建,则不必保留这些记忆,但切换需要更多时间。
您也可以尝试使用 JTabbedPane 来使用选项卡(它比 CardLayout 更容易,因为它会自动处理显示/隐藏)
其他人回答了这个问题。我想建议您使用 JTabbedPane 而不是替换内容。作为一般规则,让应用程序的视觉元素消失或被其他内容替换是不好的。当然,每条规则都有例外,只有您和您的用户社区才能决定最佳方法。
我遇到了完全相同的问题!不可思议!!我找到的解决方案是:
// 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。
问题:我的组件添加到容器后没有出现。
添加组件后,您需要调用revalidate和repaint , 然后它才会显示在您的容器中。
来源:http ://docs.oracle.com/javase/tutorial/uiswing/layout/problems.html
layout.replace() 答案仅在 GroupLayout 管理器上存在/有效。
其他 LayoutManagers(CardLayout、BoxLayout 等)不支持此功能,但需要您先 RemoveLayoutComponent( 然后 AddLayoutComponent( 再次返回。:-) [只是设置记录]
Game game = new Game();
getContentPane().removeAll();
setContentPane(game);
getContentPane().revalidate(); //IMPORTANT
getContentPane().repaint(); //IMPORTANT
我建议您在创建框架时添加两个面板,然后通过在两者上调用 setVisible(true/false) 来更改可见面板。调用 setVisible 时,将通知父级并要求重新绘制自己。
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
}
有时您可以在不使用重新验证的情况下完成工作,有时不使用重新绘制。我的建议是两者都使用。
只需在设置, ( ,可能更旧)之后调用方法pack() ,如下所示: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();
...