Skip to content

Java Swing BoxLayout layout of outer panel changes when I specify layout of inner panel

I’m very new to Java Swing. I’m using y-axis BoxLayout on an “outer” panel that contains 2 inner panels. Here you can see with this basic code, the 2 inner panels get an equal share of the height avaiable in the box layout (first inner panel yellow, second innner panel orange)

// main test frame
public class MainFrame extends JFrame {
    
    public MainFrame()
    {
        
        this.setSize(500, 500);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        this.setLayout(new GridLayout(1,1));

        // outer panel: groupWrapPanel with BoxLayout
        JPanel groupWrapPanel = new JPanel();
        groupWrapPanel.setBackground(Color.blue);
        
        groupWrapPanel.setLayout(new BoxLayout(groupWrapPanel, BoxLayout.Y_AXIS));
        
        // inner panel 1: headerPanel (yellow)
        JPanel headerPanel = new JPanel();
        headerPanel.setBackground(Color.yellow);
        groupWrapPanel.add(headerPanel);
        
        // inner panel 2: headerNotesWrap (orange)
        JPanel headerNotesWrap = new JPanel();
        headerNotesWrap.setBackground(Color.orange);
        groupWrapPanel.add(headerNotesWrap);
        

        this.add(groupWrapPanel);
        this.setVisible(true);
    }
    
}

enter image description here

But then when I add seperate layout manager to one of the inner panels, the layout of the outer panel changes, and the 2 inner panels no longer get an equal share of the height of the outer panel. I can do this by adding a single line of code:

 headerPanel.setLayout(new BorderLayout());
    

enter image description here

Can someone please explain why the layout of the outer panel changes when I specify a layout manager for the inner panel, and how I can prevent this.

Thank you.

EDIT

This is a related question and is in response to a comment someone made.

“A BoxLayout will determine the preferred size of each component. If there is extra space available it will then allocate the space equally up to the maximum size of each component. That would explain why each panel is 50/50 in the first case.”

If that’s the case, how come if I change the 2 inner components from panels to labels, they no longer stretch to fill the available space inside out the outer panel? like so:

public class MainFrame extends JFrame {

public MainFrame()
{
    
    // we're going to create what shall be known as a "Group Box",
    // which groups things together
    this.setSize(500, 500);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    this.setLayout(new GridLayout(1,1));

    // outer panel: groupWrapPanel with BoxLayout
    JPanel groupWrapPanel = new JPanel();
    groupWrapPanel.setBackground(Color.blue);
    
    groupWrapPanel.setLayout(new BoxLayout(groupWrapPanel, BoxLayout.Y_AXIS));
    
    // inner label 1
    JLabel label1 = new JLabel("Label 1");
    label1.setBackground(Color.yellow);
    label1.setOpaque(true);
    groupWrapPanel.add(label1);
    
    // inner label 2
    JLabel label2 = new JLabel("Label 2");
    label2.setBackground(Color.orange);
    label2.setOpaque(true);
    groupWrapPanel.add(label2);
    
    this.add(groupWrapPanel);

    
    this.setVisible(true);
}

}

enter image description here

Thanks again

Answer

I added the following to your code:

    setVisible(true);
    System.out.println(headerPanel.getPreferredSize());
    System.out.println(headerPanel.getMaximumSize());
    System.out.println(headerNotesWrap.getPreferredSize());
    System.out.println(headerNotesWrap.getMaximumSize());

and got the following output when using the BorderLayout:

java.awt.Dimension[width=0,height=0]
java.awt.Dimension[width=2147483647,height=2147483647]
java.awt.Dimension[width=10,height=10]
java.awt.Dimension[width=32767,height=32767]

You can see that the BorderLayout maximum size is much larger than that of the FlowLayout.

So when the extra space is allocated proportionally the BorderLayout panel gets a lot more.

A few possible solutions:

  1. Override the getMaximumSize() method of your panels that use a BorderLayout to return an appropriate value.

  2. Use a GridBagLayout. You can also stack panels in a single column.

  3. Try using the Relative Layout which can function similar to a BoxLayout and just stack panels.