From the BorderLayout javadoc:
A border layout lays out a container, arranging and resizing its components to fit in five regions: north, south, east, west, and center. Each region may contain no more than one component, and is identified by a corresponding constant: NORTH, SOUTH, EAST, WEST, and CENTER.
I have a program, based on another SO question, which creates a JFrame UI containing a button in the BorderLayout center, waits 5 seconds, then puts a different button in the same position. Because of the statement (Each region may contain no more than one component", I would expect the 2nd button to replace the first. However, the original button remains "hanging around". Here's the code:
import java.awt.BorderLayout;
import java.awt.Component;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class ReplaceBorderLayoutComponent extends JFrame
{
private static final long serialVersionUID = 1L;
public static void say(String msg) { System.out.println(msg); }
public void createUI()
{
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
try
{
SwingUtilities.invokeAndWait
(
new Runnable()
{
public void run()
{
// setLayout(new BorderLayout());
JButton longText = new JButton("Quite a long text");
/*getContentPane().*/add(longText, BorderLayout.CENTER);
pack();
setVisible(true);
say("longText = " + longText.toString());
}
}
);
}
catch (Exception e) {}
}
public void replaceComponent()
{
try
{
SwingUtilities.invokeAndWait
(
new Runnable()
{
public void run()
{
JButton anotherText = new JButton("Another text");
/*getContentPane().*/add(anotherText, BorderLayout.CENTER);
pack();
validate();
repaint();
say("anotherText = " + anotherText.toString());
}
}
);
}
catch (Exception e) { }
say("replaced");
}
public Component getComponent(String constraint)
{
BorderLayout bl = (BorderLayout)getContentPane().getLayout();
return bl.getLayoutComponent(constraint);
}
public static void main(String ... args)
{
ReplaceBorderLayoutComponent st = new ReplaceBorderLayoutComponent();
st.createUI();
try { Thread.sleep(5000); } catch (InterruptedException ie) {}
st.replaceComponent();
Component c = st.getComponent(BorderLayout.CENTER);
say("Center component = " + c.toString());
String otherPlaces[] = { "North", "South", "East", "West", "First", "Last", "Before", "After" };
for (String s : otherPlaces)
{
Component c2 = st.getComponent(s);
if (c2 != null) { say("found additional component at " + s + ", " + c2.toString()); }
}
}
}
When I run it, the first button duly takes up all the space of the frame. If I resize it, it expands as expected. When the delayed code runs, it puts the second button in the frame, but if I expand the frame, I can see both buttons. The second button expands as is normal for the center component; the first button remains the size that it was at the time the second button was added (expanded, for instance, if I expand the frame before the addition).
After adding, hovering over the second button hides the first; resizing the frame redisplays the first on top of the second. If the first button is not visible, hovering over its position will display it, at least sometimes.
I have to conclude that the first button is still a part of the frame layout somewhere (it shows default animation on being clicked, for instance), but I can't figure out where. I have code to ensure that it is not in any of the other BorderLayout components, and that the center component is indeed the second button.
I removed one and both calls to pack() - same behavior with respect to the two buttons.
The poster of the original question got around his problem by removing the first component before adding the second, but I would like to understand where the first button is still being referenced in this program. Can anyone help?