大多数布局管理器都有无参数构造函数(也就是说,您可以使用new FlowLayout ()
创建FlowLayout,使用new GridLayout ()
创建GridLayout,使用new GridBagLayout ()
创建GridBagLayout等)。但是,BoxLayout
要求您同时传递它将管理的容器和应沿其布局组件的轴。
我的问题是:既然你已经告诉布局管理器要布局哪个组件,你为什么需要编写
BoxLayout bl = new BoxLayout(myPanel, BoxLayout.Y_AXIS);
myPanel.setLayout(bl);
而不仅仅是第一行?
我快速浏览了BoxLayout
源代码,发现我使用的构造函数(第 178-185 行)没有调用 target.setLayout(this)
或类似的东西。似乎只是添加它非常简单。有什么原因为什么它不包含在 Swing 库中?
如果重要,我正在使用
Java 版本 1.7.0
Java(TM) SE 运行时环境(build 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);
}
}
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);
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(),其中确实重置了缓存的详细信息。其他布局实现遵循相同的模式。例如,GroupLayout 和 OverlayLayout 在其构造函数中也需要容器参数。