如何更改JFrame中的JPanel?
简单来说,有一个简单的java swing应用程序,它由JFrame和其中的一些组件组成。 其中一个组件是一个JPanel,它意味着在用户操作上被另一个JPanel所取代。
那么做这样的事情的正确方法是什么? 我试过了
panel = new CustomJPanelWithComponentsOnIt(); parentFrameJPanelBelongsTo.pack();
但这是行不通的。 你会build议什么?
您的使用案例,对于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使用“按值复制引用”parameter passing。 所以改变一个variables不会改变传递给其他方法的引用的副本。
另外请注意JFrame
在可用性的名称是非常混乱的。 添加组件或设置布局(通常)在内容窗格上执行操作。 奇怪的是,获得布局真的给你框架的布局pipe理器。
希望这段代码给你一个改变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()
那么你可以根据需要调整你的wndow。
这一切都取决于它将如何使用。 如果您想要在这两个面板之间来回切换,请使用CardLayout。 如果你只是从第一个切换到第二个(而不是返回),那么我会使用telcontar的build议,只是将其replace。 虽然如果JPanel不是你的框架中唯一的东西,我会使用remove(java.awt.Component)而不是removeAll。
如果你在这两种情况之间的某个地方,它基本上是一个时空关系。 CardLayout将节省您的时间,但占用更多的内存,因为必须始终将这个整个其他面板保存在内存中。 但是,如果您只是在需要时更换面板并根据需要构build面板,则不必保持这种可能性,但需要更多时间进行切换。
你也可以尝试一个JTabbedPane来使用标签来代替(它比CardLayout更容易,因为它自动处理显示/隐藏)
其他人回答了这个问题。 我想build议你使用JTabbedPane而不是replace内容。 通常,应用程序的视觉元素消失或被其他内容替代是不好的。 当然,每条规则都有例外,只有你和你的用户社区才能决定最好的方法。
我有完全相同的问题! Increadible! 我find的解决scheme是:
- 将所有组件(JPanels)添加到容器中;
- 对所有的人使用setVisible(false)方法;
- 在用户操作上,将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(),没有validation(),没有CardLayout需要。
layout.replace()答案只存在/在GroupLayoutpipe理器上工作。
其他布局pipe理器(CardLayout,BoxLayout等)不支持此function,但需要您先将RemoveLayoutComponent(然后AddLayoutComponent(再次回来。:-) [只需设置logging]
我build议你在创build框架时添加两个面板,然后通过调用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 }
有时你可以不使用重新validation,有时不使用重新绘制工作,我build议使用两者。
问题 :我的组件在添加到容器后没有出现。
添加组件之前,需要调用revalidate和repaint , 然后才会显示在容器中。
资料来源: http : //docs.oracle.com/javase/tutorial/uiswing/layout/problems.html
只需在设置ContentPane
( java 1.7
,也许更老)之后调用方法pack()就可以了:
JFrame frame = new JFrame(); JPanel panel1 = new JPanel(); JPanel panel2 = new JPanel(); .... frame.setContentPane(panel1); frame.pack(); ... frame.setContentPane(panel2); frame.pack(); ...
你可以使用布局的replace方法:
layout.replace(existingComponent, newComponent)
现有的和新的组件也可以是JPanels。