How do I remove an old JPanel and add a new one?
Solution 1
setVisible(false), even in the correct place, will not actually remove the panel from the container. If you want to replace the panel do this:
frame.getContentPane().remove(partnerSelectionPanel);
frame.add(new JPanel());
frame.getContentPane().invalidate();
frame.getContentPane().validate();
Note that frame.getContentPane().add(Component) is the same as frame.add(Component) - the components are actually contained within the content pane.
Solution 2
Don't forget or overlook the approach of using the Layout, namely the CardLayout as the Frames Layout, to allow this type of behavior (This is a good strategy for a "Wizard" for example). One advantage to this is it doesn't cause any weird flash or draw effects as that is what this Layout is meant to do--Allow a panels to be swapped out, assuming they have exclusive "real estate" or can share the same areas (i.e. "Wizard" like behavior.)
Solution 3
You can use
Frame.setContentPane(jPanel);
Roman
Updated on September 27, 2020Comments
-
Roman over 3 years
I would like to remove an old JPanel from the Window (JFrame) and add a new one. How should I do it?
I tried the following:
public static void showGUI() { JFrame frame = new JFrame("Colored Trails"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(partnerSelectionPanel); frame.setSize(600,400); frame.setVisible(true); } private static void updateGUI(final int i, final JLabel label, final JPanel partnerSelectionPanel) { SwingUtilities.invokeLater( new Runnable() { public void run() { label.setText(i + " seconds left."); } partnerSelectionPanel.setVisible(false); \\ <------------ } ); }
My code updates the "old" JPanel and then it makes the whole JPanel invisible, but it does not work. The compiler complains about the line indicated with
<------------
. It writes:<identifier> expected, illegal start of type
.ADDED:
I have managed to do what I needed and I did it in the following way:
public static void showGUI() { frame = new JFrame("Colored Trails"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(partnerSelectionPanel); //frame.add(selectionFinishedPanel); frame.setSize(600,400); frame.setVisible(true); } public static Thread counter = new Thread() { public void run() { for (int i=4; i>0; i=i-1) { updateGUI(i,label); try {Thread.sleep(1000);} catch(InterruptedException e) {}; } partnerSelectionPanel.setVisible(false); frame.add(selectionFinishedPanel); } };
It works but it does not look to me like a safe solution for the following reasons:
- I change and add elements to the JFrame from another thread.
- I add a new JPanel to a JFrame, after I have already "packed" the JFrame and made it visible.
Should I be doing that?
-
Roman about 14 yearsRuss Hayward, Is it OK to remove and add JPanels after the JFrame is already packed and set visible? Should I add and remove JPanels in the events dispatch thread?
-
Roman about 14 yearsAfter I have replaced the
partnerSelectionPanel.setVisible(false);
by theframe.getContentPane().remove(partnerSelectionPanel);
, my program stopped to remove the old frame (even if I useinvalidate
in the end). -
Russ Hayward about 14 yearsYes adding, removing and creating components should happen on the EDT. I missed off a validate call - I never remember those! Should work if you add the invalidate and the validate.
-
Wintermut3 about 14 yearsJust keep in mind as to the Visible accessors that those are useful to cause the user from seeing a "shuffle" or a lot of flashing as any particular component is updated not only that but updating certain components while they are setVisible(false) can dramatically improve performance--really the usefulness and even success of this strategy seem to vary per component or even between different versions of the JDK, Also don't forget you can re-"pack" the frame after you have swapped the panels.