前言
如何布局一直是Java Swing中一个令人头疼的问题。老实说,Java官方给出的几种布局管理器实现,都不怎么好用。不过,合理利用多种布局和JPanel
的组合,倒也足以完成大部分布局需求了。本文就简单讲解一下BoxLayout
这个灵活的布局管理器。
BoxLayout
BoxLayout
即盒子布局,允许组件水平或垂直排列,这一点有点类似于FlowLayout
,不过FlowLayout
是不支持垂直排列的。BoxLayout
的构造方法如下:
BoxLayout(Container target, int axis)
第一个参数是目标容器,axis
则是BoxLayout
的排列方式,一般选择X_AXIS
或者Y_AXIS
。前者代表组件从左至右排列,后者代表组件从上至下排列。典型的使用方式如下:
public class BoxLayoutTest {
public static void main(String[] args) {
JPanel boxPanel=new JPanel();
BoxLayout boxLayout=new BoxLayout(boxPanel,BoxLayout.Y_AXIS);
boxPanel.setLayout(boxLayout);
boxPanel.add(new JButton("Button1"));
boxPanel.add(new JButton("Button2"));
boxPanel.add(new JButton("Button3"));
JFrame frame=new JFrame();
frame.setContentPane(boxPanel);
frame.pack();
frame.setVisible(true);
}
}
运行结果:
可以看到,三个按钮按照我们预期的方式垂直排列在窗体中。但是,在实际开发中我们往往不会直接使用BoxLayout
,而是使用Swing中的Box
组件,这是一种更加轻量级的方式。
Box
Box
是使用BoxLayout
作为布局管理器的轻量级容器,使用Box
和Box提供的填充物
可以设计出非常灵活的布局。在下文我们将设计出这样的布局:
首先我们要知道如何构建出一个Box
对象。一般而言,我们会使用Box的createHorizontalBox
或createVerticalBox
方法构建一个Box。它们都是静态方法,前者将创建一个从左到右显示其组件的Box,后者创建一个从上到下显示其组件的Box。这两个方法的原型如下:
public static Box createHorizontalBox()
public static Box createVerticalBox()
根据实际情况,我们可以选用不同排列方向的Box,并可以借助Box的相互嵌套构造出复杂的布局。需要注意的是,Box的组件之间默认是没有空隙的。换句话说,在Box内的组件都是紧密相邻的,这显然不够美观。幸运的是,Box还提供了三种不可见的组件用于辅助布局,即glue、struts和rigid区域
。这三种组件都需要通过Box的静态方法创建,方法原型如下:
public static Component createHorizontalStrut(int width)
public static Component createVerticalStrut(int height)
public static Component createHorizontalGlue()
public static Component createVerticalGlue()
public static Component createRigidArea(Dimension d)
一般情况下,我们使用strut
作为填充物
,strut
具有固定的高度或宽度。根据具体要求,可以使用横向的strut
和纵向的strut
。
下面,我们将给出一个具体的例子:
public class BoxLayoutTest {
public static void main(String[] args) {
JFrame frame=new JFrame();
frame.setSize(360,150);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//垂直方向的Box
Box verticalBox=Box.createVerticalBox();
//水平方向的第一个Box
Box rowBox1=Box.createHorizontalBox();
JLabel label=new JLabel("基本信息表",JLabel.CENTER);
rowBox1.add(label);
//水平方向的第二个Box
Box rowBox2=Box.createHorizontalBox();
rowBox2.add(new JLabel("姓名:"));
rowBox2.add(createBoxItemField());
rowBox2.add(Box.createHorizontalStrut(20));
rowBox2.add(new JLabel("年龄:"));
rowBox2.add(createBoxItemField());
//水平方向的第三个Box
Box rowBox3=Box.createHorizontalBox();
rowBox3.add(new JLabel("性别:"));
rowBox3.add(createBoxItemField());
rowBox3.add(Box.createHorizontalStrut(20));
rowBox3.add(new JLabel("电话:"));
rowBox3.add(createBoxItemField());
verticalBox.add(Box.createVerticalStrut(10));
verticalBox.add(rowBox1);
verticalBox.add(Box.createVerticalStrut(10));
verticalBox.add(rowBox2);
verticalBox.add(Box.createVerticalStrut(10));
verticalBox.add(rowBox3);
verticalBox.add(Box.createVerticalStrut(10));
frame.add(verticalBox);
frame.setVisible(true);
}
//创建具有最大尺寸的JTextField
private static JTextField createBoxItemField(){
JTextField field=new JTextField(10);
field.setMaximumSize(field.getPreferredSize());
return field;
}
}
可以看到,在上述代码中,我们使用了四个Box
对象,第一个Box是一个垂直方向的Box,用于放置其他Box对象。其他Box对象都是水平方向的Box。第二个Box用于放置标题文字,第三个Box和第四个Box用于放置具体的组件。可以看到,我们还不时使用strut
作为填充物
辅助布局。最后,我们将垂直方向的Box添加到了JFrame
中。
此外,我们定义了一个静态方法createBoxItemField
,用于快速创建JTextField
对象。需要注意的是,对于每个创建的JTextField
对象,我们都调用了它的setMaximumSize
方法,即设置该组件的最大大小。这样做的目的是令组件以最合适的大小显示在Box
中,否则,像JTextField
这样的组件将会被Box
拉伸,影响最终的布局效果。