Travis Truttschel
Travis Truttschel

Reputation: 137

Unable to add to JFrame after removeAll()

I have a relatively small class called "LoadingWindow" this class has a constructor that calls a Initialize function to setup the frame. Not I was testing some things to try to solve why it would not update. While testing I added "this.removeAll();" to the head of the initialize method. Turns out, I cant add anything after that. Anything I add, simply will not show.

Here is a slightly trimmed down version of the class:

public class LoadingWindow extends JFrame{

public JPanel panel;

public JProgressBar bar;

private JLabel label;

public LoadingWindow()
{

    this.Initialize();

}

public void Initialize()
{
    this.removeAll();

    this.setSize(300, 150);

    panel = new JPanel(new BorderLayout());
    bar = new JProgressBar(0,100);
    label = new JLabel("Please remain calm, we're just loading...");

    panel.add(bar,BorderLayout.CENTER);
    panel.add(label,BorderLayout.SOUTH);

    this.add(panel);

    this.validate();
    this.repaint();
    this.setVisible(true);
}
}

The window itself does pop up properly, with a title. However the window itself is completely blank.

I implement this class statically so that four other objects can access it in the EditorPanel class. Its defined as:

public static LoadingWindow loadingWindow;

and initialized in the constructor with:

loadingWindow = new LoadingWindow();

There is then a double check within the functions that use it to show it if it is hidden.

if(!EditorPanel.loadingWindow.isVisible()){EditorPanel.loadingWindow.Initialize();}

Overall I'm a bit confused as to why no content is showing, and I am very interested in any questions asked, and am willing to provide any info necessary. Google didn't provide a whole lot, and every answer I found I had already implemented "such as repaint and validate".

I look forward to hearing from you!

~Travis

Upvotes: 4

Views: 4163

Answers (2)

David Kroukamp
David Kroukamp

Reputation: 36423

removeAll() as said by @TomHawtintackline (+1 to him), is not forwarded to the JFrames contentPane; like add(), remove() or setLayout() is.

Thus when you do JFrame#removeAll() it removes the root pane of JFrame. See How to Use Root Panes for an interesting read and may prove fruitful for future endeavors.

You should do:

getContentPane().removeAll();// will make sure we remove all components from the contentPane

  • Also dont extend JFrame unnecessarily (unless adding functionality beyond its current capability) rather just create an instance of JFrame and use that

  • Dont call setSize rather use an appropriate LayoutManager and/or override getPreferredSize() of JPanel and return dimensions which fit drawings, thus you can call pack() on JFrame before setting it visible.

  • I see no need for validate() and repaint() these should only be called when a component is added to a visible container. Even than rather do revalidate() which will work for adding and removing a component (it inturn calls validate())

Upvotes: 14

Tom Hawtin - tackline
Tom Hawtin - tackline

Reputation: 147164

I am guessing removeAll removes the root pane.

JFrame is a container and contains a number of components that are part of what we think of as the frame. There was a hack introduced into JFrame (and JApplet), so that some methods act on the content pane instead of the frame itself. Use a different method, or one of the special methods when the forwarding is not in force, and it'll screw up.

See the API docs for JFrame.remove and note that removeAll is not overridden.

The safest solution is to ignore the "helpful" forwarding, and manipulate the content pane itself (either through getContentPane, or possible better create your own JPanel and use setContentPane). (Also don't extend classes, such as JFrame or Thread, unnecessarily and follow standard coding conventions.)

Upvotes: 3

Related Questions