2

I'm using a BoxLayout and removing components from it dynamically, something like this:

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            final JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
            final JLabel l = new JLabel("remove");
            frame.add(l);
            frame.add(new JLabel("Hello2"));
            frame.add(new JLabel("Hello3"));
            frame.pack();
            frame.setVisible(true);

            new Thread() {
                public void run() {
                    Utils.sleep(1000);
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            frame.remove(l);
                            frame.repaint();
                        }
                    });
                }
            }.start();
        }
    });
}

However, when doing so, even though the label in question is removed from the layout, the other components don't shift up to cover its space until I resize the frame. I tried repainting the frame after removing the component, but no luck - the label no longer displays but there's still the gap where it used to be.

Apart from the obviously horrible bodge of resizing the window automatically every time the component is removed, how do I get the desired behaviour?

Michael Berry
  • 70,193
  • 21
  • 157
  • 216

2 Answers2

5

You need to invoke validate() on frame as well.


SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        frame.remove(l);
        frame.validate();
        frame.repaint();
    }
});
Moonbeam
  • 2,283
  • 1
  • 15
  • 17
  • Thanks, `validate()` was exactly what I was after - I should've remembered that but my swing knowledge is rather rusty! – Michael Berry Jul 27 '11 at 13:26
  • @berry120, No problem. And if you want the entire `frame` to re-size itself, invoke `frame.pack()` instead of `frame.validate()`. The components will still shift, but the `frame` will also adjust itself accordingly. – Moonbeam Jul 27 '11 at 13:30
4

1/ put revalidate(); before repaint();

2/ better would be invoke Thread from Runnable not from invokeLater()

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • Thanks for the answer - `validate()` was what I needed. In terms of the second point, I completely agree - this was just a quick thing I knocked together in a few minutes to demonstrate the problem rather than anything I'll actually use! – Michael Berry Jul 27 '11 at 13:27
  • +1, For correct answer and suggestion as well. Also, `revalidate()` isn't a method recognized by `JFrame` since it doesn't extend `JComponent`! :) – Moonbeam Jul 27 '11 at 13:31
  • @Moonbeam yes that's so heavy hammer for GUI – mKorbel Jul 27 '11 at 13:32