1

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?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
gummbahla
  • 219
  • 2
  • 13

1 Answers1

0

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();
    }
}
arcy
  • 12,845
  • 12
  • 58
  • 103
  • 3
    I'm pretty sure for `JFrame`s, `frame.getContentPane().add` is equivilent to `frame.add()` – Cruncher Sep 06 '13 at 19:32
  • Yes, as it turns out, you can remove getContentPane() from the above. And there's no need to set borderLayout on the content pane, that's its default... – arcy Sep 06 '13 at 19:39
  • Well, back when I was in high school, we used null layout for everything lol. It's crippled me forever since. – Cruncher Sep 06 '13 at 19:44
  • @rcook Thanks for the feedback. Doing all the stuff in the constructor is just for the sake of the example :) However, in my case I _need_ to add things after setVisible(). The only way I got it working for now, is by manually removing the CENTER component from the layout, before adding the new component: BorderLayout l = new BorderLayout(); ... getContentPane().remove(l.getLayoutComponent(BorderLayout.CENTER)); – gummbahla Sep 07 '13 at 06:14