为什么需要使用BoxLayout调用setLayout?

时间:2012-06-03 04:23:55

标签: java swing layout layout-manager boxlayout

大多数布局管理器都没有参数构造函数(也就是说,您可以使用new FlowLayout ()创建FlowLayout,使用new GridLayout ()创建GridLayout,使用new GridBagLayout ()创建GridBagLayout等等。但是,BoxLayout要求您传递它将要管理的容器以及应该布置组件的轴。

我的问题是:既然您已经告诉布局管理器要布局哪个组件,为什么还需要编写

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

而不仅仅是第一行?

我快速浏览了the BoxLayout source code并看到我使用的构造函数(第178-185行)没有调用target.setLayout(this)或任何类型的东西。看起来添加它真的很简单。有没有理由不将它包含在Swing库中?

如果重要,我使用

  

java version 1.7.0

     

Java(TM)SE运行时环境(版本1.7.0-b147)

在Win7Pro上。

谢谢!


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);
    }
}

2 个答案:

答案 0 :(得分:5)

Container必须存在才能传递给BoxLayout。通常一个人写这样的东西:

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

结合最后两行是很诱人的,但是最不惊讶的原则表明布局的构造函数不应该改变容器的状态。

通常,javax.swing.Box提供“使用BoxLayout对象作为其布局管理器的轻量级容器。”

public class Box extends JComponent implements ... {

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

现在只需一行:

Box myBox = new Box(BoxLayout.Y_AXIS);

答案 1 :(得分:4)

BoxLayout确保将布局方法应用于正确的容器。它强制在构造函数中指定的同一容器用于各种方法,例如layoutContainer(Container target)preferredLayoutSize(Container target)等。它归结为执行验证的checkContainer()方法:

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

BoxLayout实现可能会缓存有关容器的一些细节并尝试维护状态,因此无法共享。

编辑:

BoxLayout实现LayoutManager2.invalidateLayout(),它会重置其缓存的详细信息。其他布局实现遵循相同的模式。例如,GroupLayoutOverlayLayout在其构造函数中也需要容器参数。