Why do you need to invoke setLayout with BoxLayout?
Asked Answered
W

2

9

Most layout managers have no-argument constructors (that is, you can create a FlowLayout with new FlowLayout (), a GridLayout with new GridLayout (), a GridBagLayout with new GridBagLayout (), etc.). However, BoxLayout requires that you pass both the container that it will be managing and the axis along which the components should be laid out.

My question is: since you're already telling the layout manager which component to lay out, why do you need to write

BoxLayout bl = new BoxLayout(myPanel, BoxLayout.Y_AXIS);
myPanel.setLayout(bl);

instead of just the first line?

I took a quick look at the BoxLayout source code and saw that the constructor I use (lines 178-185) doesn't make a call to target.setLayout(this) or anything of the sort. It seems like it would be really simple to just add that. Is there a reason why it's not included in the Swing library?

If it matters, I'm using

java version 1.7.0

Java(TM) SE Runtime Environment (build 1.7.0-b147)

on Win7Pro.

Thanks!


SSCCE:

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;

public class BoxLayoutSSCCE extends JFrame {

    // Change this to see what I mean
    public static final boolean CALL_SET_LAYOUT = true;

    public BoxLayoutSSCCE () {
        super("Box Layout SSCCE");
        JPanel panel = new JPanel();
        BoxLayout bl = new BoxLayout(panel, BoxLayout.Y_AXIS);
        if (CALL_SET_LAYOUT) {
            panel.setLayout(bl);
        }
        panel.add(new JButton("Button 1"));
        panel.add(new JButton("Button 2"));
    }

    public static void main (String[] args) {
        BoxLayoutSSCCE blsscce = new BoxLayoutSSCCE();
        blsscce.pack();
        blsscce.setVisible(true);
    }
}
Washhouse answered 3/6, 2012 at 4:23 Comment(1)
+1 for sscce.Pasteurization
P
5

The Container must exist before it can be passed to BoxLayout. Typically one writes something like this:

JPanel myPanel = new JPanel();
BoxLayout bl = new BoxLayout(myPanel, BoxLayout.Y_AXIS);
myPanel.setLayout(bl);

It's tempting to combine the last two lines, but the principle of least astonishment suggests that the layout's constructor should not otherwise alter the container's state.

Convenienly, javax.swing.Box provides "A lightweight container that uses a BoxLayout object as its layout manager."

public class Box extends JComponent implements ... {

    public Box(int axis) {
        super();
        super.setLayout(new BoxLayout(this, axis));
    }
}

Now a single line will do:

Box myBox = new Box(BoxLayout.Y_AXIS);
Pasteurization answered 3/6, 2012 at 7:41 Comment(1)
You're welcome; for reference, the design is consistent with the principle discussed here.Pasteurization
J
4

BoxLayout makes sure that the layout methods are applied to the correct container. It enforces that the same container that was specified in the constructor is used in various methods, such as layoutContainer(Container target), preferredLayoutSize(Container target), etc. It boils down to the checkContainer() method that does the verification:

void checkContainer(Container target) {
    if (this.target != target) {
        throw new AWTError("BoxLayout can't be shared");
    }
}

BoxLayout implementation probably caches some details about the container and tries to maintain state, so it cannot be shared.

EDIT:

BoxLayout implements LayoutManager2.invalidateLayout() where it does reset its cached details. Other layout implementations follow the same pattern. For example, GroupLayout and OverlayLayout also require container argument in their constructors.

Jaleesa answered 3/6, 2012 at 5:26 Comment(2)
I understand that it can't be shared. However, as it can't be shared, it seems logical that that the component will have to set it as its layout - why doesn't BoxLayout just call setLayout(container) in the constructor? In addition, why don't other managers enforce this?Washhouse
@WChargin The argument specified in the constructor is used by BoxLayout to verify and apply the restriction. Also, see my edit about other managers.Jaleesa

© 2022 - 2024 — McMap. All rights reserved.