BoxLayout布局管理器

时间:2023-01-28 20:23:56

前言

如何布局一直是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布局管理器

可以看到,三个按钮按照我们预期的方式垂直排列在窗体中。但是,在实际开发中我们往往不会直接使用BoxLayout,而是使用Swing中的Box组件,这是一种更加轻量级的方式。

Box

Box是使用BoxLayout作为布局管理器的轻量级容器,使用BoxBox提供的填充物可以设计出非常灵活的布局。在下文我们将设计出这样的布局:

BoxLayout布局管理器

首先我们要知道如何构建出一个Box对象。一般而言,我们会使用Box的createHorizontalBoxcreateVerticalBox方法构建一个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拉伸,影响最终的布局效果。