Search code examples
javaswingjframelayout-managerborder-layout

BorderLayout - child component remains visible after adding another component


I try to do the following thing:

  1. Add a component to a JFrame with a BorderLayout
  2. Add another component to the JFrame

I would expect the new component to 'overwrite' the old component, since I'm using a BorderLayout. This works if I overwrite the old component before I call pack(). Now if I add the 2nd component after I call pack(), both components remain visible. Example:

public class Test extends JFrame{
    public Test(){
        setLayout(new BorderLayout());
        add(new JLabel("Quite a long text"));
        setVisible(true);
        pack();
        add(new JLabel("Another text"));
    }
}

Result: Calling pack() before adding the component

public class Test extends JFrame{
    public Test(){
        setLayout(new BorderLayout());
        add(new JLabel("Quite a long text"));
        setVisible(true);
        add(new JLabel("Another text"));
        pack();
    }
}

Result: Calling pack() after adding the component

I tried adding validate(); and repaint();, but that wouldn't help. What's going wrong here?


Solution

  • You are calling things that affect the UI after setViisble() is called -- a Swing no-no. Put things that affect the UI into an invokeLater call; look it up.

    While you're at it, I think you're still supposed to get the content pane from the frame for adding components... And I don't think creating things in the constructor is a good idea.

    import java.awt.BorderLayout;
    
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.SwingUtilities;
    
    public class SwingTest extends JFrame
    {
        public void createUI()
        {
            setDefaultCloseOperation(DISPOSE_ON_CLOSE);
            SwingUtilities.invokeLater(
                    new Runnable()
                    {
                        public void run()
                        {
                            getContentPane().setLayout(new BorderLayout());
                            getContentPane().add(new JLabel("Quite a long text"), BorderLayout.CENTER);
                            getContentPane().add(new JLabel("Another text"), BorderLayout.CENTER);
                            pack();
                            setVisible(true);
                        }
                    }
                    );
        }
    
        public static void main(String ... args) 
        { 
            SwingTest st = new SwingTest();
            st.createUI();
        }
    }