2

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

Geoff L
  • 765
  • 5
  • 22
  • 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. I have no idea why setting the layout manager affects the layout. Maybe the maximum size of one the panels is affected? In any case we don't know what your actual requirement is. If your requirement is keep the panels at 50/50 then use a GridLayout. – camickr Jul 22 '21 at 15:36
  • @camickr thanks for your response. My requirement is to understand why this happens. I need a BoxLayout where I can place panels in a "stack" and understand how their dimensions are calculated. As you can see I need to be able to specify layout managers for each panel in the stack. If this unexpectedly changes the layout of parent containers, it causes problems. 50/50 won't work the heights of each inner panel in the stack will need to be determined by the components inside each inner panel with a specified layout manager. – Geoff L Jul 22 '21 at 15:42
  • If you want full control you override the `getMaximumSize()` method of your panel to return the `preferred size`. Then the panel will not grow when there is extra space. You can also use a GridBagLayout to "stack" panels. I gave you a suggestion. Did you verify the preferred/maximum sizes of each panel using the different layout managers? That is does the FlowLayout and BorderLayout calculate different values? I'm guessing the maximum size of the BorderLayout is larger. – camickr Jul 22 '21 at 15:50
  • These are dimensions of the 2 inner panels before i specify a layout manager for inner panel 1: pref inner1=java.awt.Dimension[width=10,height=10] min inner1=java.awt.Dimension[width=10,height=10] max inner1=java.awt.Dimension[width=32767,height=32767] pref inner2=java.awt.Dimension[width=10,height=10] min inner2=java.awt.Dimension[width=10,height=10] max inner2=java.awt.Dimension[width=32767,height=32767] – Geoff L Jul 22 '21 at 15:58
  • These are dimension of the 2 inner panels after i specify a layout manager for inner panel 1: pref=java.awt.Dimension[width=0,height=0] min=java.awt.Dimension[width=0,height=0] max=java.awt.Dimension[width=2147483647,height=2147483647] pref=java.awt.Dimension[width=10,height=10] min=java.awt.Dimension[width=10,height=10] max=java.awt.Dimension[width=32767,height=32767]. Not sure whats going on here – Geoff L Jul 22 '21 at 15:59
  • *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?* - the maximum size of the JLabel is equal to its preferred size so it won't grow. – camickr Jul 22 '21 at 16:06
  • You're going about creating a GUI backwards. You don't first determine the size of the outer JPanels and make the Swing components fit. You create the inner JPanels first and let the Swing layout managers determine the size of the outer JPanels and JFrame. – Gilbert Le Blanc Jul 22 '21 at 17:48

1 Answers1

1

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.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • Ah ok. In the comments above I did the same test and noticed the difference. I guess to main issue is I don't understand how preferred, min, and max sizes combine to determine the layout. I can definitely override getMaximumSize to limit the size of each container, I just wanted to know why the issue existed in the first place. In the case of BoxLayout, what I'm understanding is that it will first set a minimum size for each component based on getMinimumSize, and then allocate extra space based on the relative sizes of getMaxSize for each component. Where does getPreferredSize come in? Thanks – Geoff L Jul 22 '21 at 16:05
  • No, I already stated it uses the preferred size (not the minimum size) as the starting point. The minimum size comes in to play if you shrink the size of the frame. – camickr Jul 22 '21 at 16:08