views:

10129

answers:

8

To put it simple, there's a simple java swing app that consists of JFrame with some components in it. One of the components is a JPanel that is meant to be replaced by another JPanel on user action.

So, what's the correct way of doing such a thing? I've tried

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

but this won't work. What would you suggest?

+2  A: 
frame.setContentPane(newContents());
frame.revalidate(); // frame.pack() if you want to resize.

Remember, Java use 'copy reference by value' argument passing. So changing a variable wont change copies of the reference passed to other methods.

Also note JFrame is very confusing in the name of usability. Adding a component or setting a layout (usually) performs the operation on the content pane. Oddly enough, getting the layout really does give you the frame's layout manager.

Tom Hawtin - tackline
Tom, thanks for your reply. I'm not aiming to replace the contentpane, just a jpanel placed on it (like frame.add(jpanel1), frame.add(jpanel2), frame.add(jpanel3)). Could you plz suggest a sane solution in code?
alex
Hey John,Your use case, seems perfect for CardLayout. http://java.sun.com/docs/books/tutorial/uiswing/layout/card.htmlIn card layout you can add multiple panels in the same place, but then show or hide, one panel at a time.
swapnonil
@swapnonil: Make that an answer so I can vote it up. :)
Michael Myers
A: 

I suggest you to add both panel at frame creation, then change the visible panel by calling setVisible(true/false) on both. When calling setVisible, the parent will be notified and asked to repaint itself.

Riduidel
+2  A: 

1) Setting the first Panel:

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

2)Replacing the panel:

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

Also notice that you must do this in the Event's Thread, to ensure this use the SwingUtilities.invokeLater or the SwingWorker

Telcontar
+1  A: 

The other individuals answered the question. I want to suggest you use a JTabbedPane instead of replacing content. As a general rule, it is bad to have visual elements of your application disappear or be replaced by other content. Certainly there are exceptions to every rule, and only you and your user community can decide the best approach.

James A Wilson
+11  A: 

Your use case, seems perfect for CardLayout.

In card layout you can add multiple panels in the same place, but then show or hide, one panel at a time.

swapnonil
When using CardLayout, keep in mind that the preferred size for the panel that uses it will be the size of the LARGEST panel in the layout. If you want the space to be reclaimed, you will want to use setVisible(false) and setPreferredSize( new Dimension( 0,0 ) ) to hide a component.
Joseph Gordon
I hadn't heard of CardLayout before. Thanks - was perfect for something I needed to do.
I82Much
A: 

It all depends on how its going to be used. If you will want to switch back and forth between these two panels then use a CardLayout. If you are only switching from the first to the second once and (and not going back) then I would use telcontars suggestion and just replace it. Though if the JPanel isn't the only thing in your frame I would use remove(java.awt.Component) instead of removeAll.

If you are somewhere in between these two cases its basically a time-space tradeoff. The CardLayout will save you time but take up more memory by having to keep this whole other panel in memory at all times. But if you just replace the panel when needed and construct it on demand, you don't have to keep that meory around but it takes more time to switch.

Also you can try a JTabbedPane to use tabs instead (its even easier than CardLayout because it handles the showing/hiding automitically)

luke
A: 

On the user action:

// you have to do something along the lines of

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

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

Then you can resize your wndow as needed.

ShawnD
A: 

Hope this piece of code give you an idea of changing jPanels inside a JFrame.

enter code here

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

}

}