5

Here is runnable piece of code explaining the problem -

I can remove s1 and s2 but not s3.
This does not seem MigLayout related (I happen to be using it) as I see the same behavior with default layout as well.


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import net.miginfocom.swing.MigLayout;

public class MyFrame2 extends JFrame {
    private JPanel main;
    private JPanel s1;
    private JPanel s2;
    private JPanel s3;

    public static void main(String[] args) throws InterruptedException {
        MyFrame2 f = new MyFrame2();
        f.setVisible(true);
        Thread.sleep(2000); //you can see all three panels for two seconds

        f.main.remove(f.s1);
        f.main.validate();
        Thread.sleep(2000);
        f.main.remove(f.s2);
        f.main.validate();
        Thread.sleep(2000);
        f.main.remove(f.s3);
        f.main.validate();
    }

    public MyFrame2() {
        main = new JPanel();

        main.setLayout(new MigLayout());

        main.add(new JLabel("Why does s3 not disappear?"),"w 200, h 100, wrap");

        s1 = new JPanel();
        s1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY,1),"s1"));
        main.add(s1,"w 90%, h 300, wrap");

        s2 = new JPanel();
        s2.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY,1),"s2"));
        main.add(s2,"w 90%, h 300, wrap");

        s3 = new JPanel();
        s3.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.GRAY,1),"s3"));
        main.add(s3,"w 90%, h 300, wrap");

        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(main, BorderLayout.CENTER);

        setSize(new Dimension(800, 600));

    }
}

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Amol Katdare
  • 6,740
  • 2
  • 33
  • 36

2 Answers2

11

Call at the end, after the last f.validate():

f.repaint(50L);

As the last validate does not change layouting.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • Thanks. It works! (+1). can you please elaborate a little? Why does the last validate not change layouting while all previous validates do? (Clearly i don't do much swing development!) – Amol Katdare Feb 07 '12 at 00:43
  • 2
    The last validate *does* change the layout -- you just don't see it. The last component has been in fact removed after the call to validate, but you need to repaint the component in order to see the visual proof of this removal. – Hovercraft Full Of Eels Feb 07 '12 at 00:56
  • Thanks Hovercraft (+1). Why is repaint not required to reflect visual changes on earlier removals (of s1 and s2)? – Amol Katdare Feb 07 '12 at 15:58
5

First, Swing GUI objects should be constructed and manipulated only on the event dispatch thread, but you mustn't sleep on the EDT. Instead use javax.swing.Timer to mark time, as shown here.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • 1
    @amol: The sibling components were affected, resized, and had to be redrawn in the validate. The last component did not trigger such redrawing. (sorry wrong spot of this comment) – Joop Eggen Feb 07 '12 at 18:35