网格组布局管理器

由GridBagLayout类实现的布局管理器称为网格组布局管理器,它 实现了一个动态的矩形网格,这个矩形网格由无数个矩形单元格组成, 每个组件可以占用一个或多个这样的单元格。所谓动态的矩形网格,就 是可以根据实际需要随意增减矩形网格的行数和列数。

在向由GridBagLayout类管理的容器中添加组件时,需要为每个组 件创建一个与之关联的GridBagConstraints类的对象,通过该类中的属性 可以设置组件的布局信息,如组件在网格组中位于第几行、第几列,以 及需要占用几行几列等。

通过GridBagLayout类实现的矩形网格的绘制方向由容器决定,如 果容器的方向是从左到右,则位于矩形网格左上角的单元格的列索引为 0,此时组件左上角的点为起始点;如果容器的方向是从右到左,则位 于矩形网格右上角的单元格的列索引为0,此时组件右上角的点为起始 点。

下面就详细讲解GridBagLayout类中各个属性的功能和使用方法, 以及在使用过程中需要注意的一些事项。

(1)gridx和gridy属性

这两个属性用来设置组件起始点所在单元格的索引值。需要注意的是,属性gridx设置的是X轴(即网格水平方向)的索引值,所以它表示 的是组件起始点所在列的索引;属性gridy设置的是Y轴(即网格垂直方 向)的索引值,所以它表示的是组件起始点所在行的索引,如图所示。

gridx和gridy属性
gridx和gridy属性

(2)gridwidth和gridheight属性

这两个属性用来设置组件占用网格组的行数和列数。属性gridwidth 为组件占用网格组的列数,也可以理解为以单元格为单位组件的宽度; 属性gridheight为组件占用网格组的行数,也可以理解为以单元格为单位 组件的高度,如图所示。

gridwidth和gridheight属性
gridwidth和gridheight属性

(3)anchor属性

属性anchor用来设置组件在其所在显示区域的显示位置。通常将显 示区域从方向上划分为9个方位,分别为北方(NORTH)、东北 (NORTHEAST)、东方(EAST)、东南(SOUTHEAST)、南方 (SOUTH)、西南(SOUTHWEST)、西方(WEST)、西北 (NORTHWEST)和中心(CENTER),如图所示。代表这9个方 位的单词也是该类中的静态常量,可以利用这9个静态常量设置anchor 属性,其中静态常量CENTER为默认位置。如图所示为将组件设置 为各个静态常量的效果,图中的黑点为将相应组件的anchor属性设置为 CENTER时组件中心所在的位置。

从方向上划分的9个方位
从方向上划分的9个方位
anchor属性
anchor属性

说明:图中的组件A至组件M是辅助组件,只起到占位作用。

(4)fill属性

属性fill用来设置组件的填充方式。当单元格显示区域的面积大于组 件面积,或者一个组件占用多个单元格时,显示组件可能不必占用所有 显示区域,在这种情况下可以通过fill属性设置组件的填充方式。可以利 用4个静态常量设置该属性,默认情况下是将该属性设置为静态常量NONE,即不调整组件大小至填满显示区域;如果将该属性设置为静态 常量HORIZONTAL,表示只调整组件水平方向的大小(即组件宽度) 至填满显示区域;如果将该属性设置为静态常量VERTICAL,表示只调 整组件垂直方向的大小(即组件高度)至填满显示区域;如果将该属性 设置为静态常量BOTH,则表示同时调整组件的宽度和高度至填满显示 区域。具体效果如图所示。

fill属性
fill属性

说明:图中的组件A至组件K是辅助组件,只起到占位作用。

(5)insets属性

属性insets用来设置组件四周与单元格边缘之间的最小距离。该属 性的类型为Insets,Insets类仅有一个构造方法Insets(int top, int left, int bottom, int right),它的4个入口参数依次为组件上方、左侧、下方和右 侧的最小距离,单位为像素,如图所示。默认为没有距离。

insets属性
insets属性

(6)ipadx和ipady属性

这两个属性用来修改组件的首选大小。属性ipadx用来修改组件的宽度,属性ipady用来修改组件的高度。如果为正数,则在首选大小的 基础上增加指定的宽度和高度,如图所示;如果为负数,则在首 选大小的基础上减小指定的宽度和高度,如图所示。

ipadx和ipady属性为正数
ipadx和ipady属性为正数
ipadx和ipady属性为负数
ipadx和ipady属性为负数

(7)weightx和weighty属性

这两个属性用来设置网格组的每一行和每一列对额外空间的分布方 式。在不设置属性weightx和weighty(即采用默认设置)的情况下,当 窗体调整到足够大时,将出现如图 所示的效果,组件全部聚集在 窗体的中央,在组件四周出现了大片的额外空间。为了避免这种情况出 现,可以通过这两个属性设置网格组的每一行和每一列对额外空间的分 布方式。

未设置属性weightx和weighty
未设置属性weightx和weighty

这两个属性的默认值均为0,表示不分布容器的额外空间。属性 weightx用来设置其所在列对额外空间的分布方式,如果在该列中设置了多个weightx属性,则取它们的最大值为该列的分布方式;属性 weighty用来设置其所在行对额外空间的分布方式,如果在该行中设置 了多个weighty属性,则取它们的最大值为该行的分布方式。

技巧:在设置网格组的每一行和每一列对额外空间的分布方式时,建议 只设置第一行的weightx属性和第一列的weighty属性,这样会方便前期 调试和后期维护。

网格组的行和列对额外空间的分布方式完全相同,下面以网格组的 行为例详细讲解对额外空间的分布方式。网格组布局管理器首先计算出 每一行的分布方式,即获取每一行的weighty属性的最大值,然后计算 每个最大值占所有最大值总和的百分比,最后将额外空间的相应百分比 分配给对应行,如图所示。

设置了属性weightx和weighty
设置了属性weightx和weighty

技巧:在设置网格组的每一行和每一列对额外空间的分布方式时,建议 为各个属性按百分比取值,如上图所示。

【例】使用网格组布局管理器。 本例实现了利用网格组布局管理器管理组件,并且使用了GridBagConstraints类中所有用来设置组件布局信息的属性,设计本例的 出发点是对比各种设置的效果。本例的关键代码如下:

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

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

public class ExampleFrame_03 extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static void main(String args[]) {
		ExampleFrame_03 frame = new ExampleFrame_03();
		frame.setVisible(true);
	}

	public ExampleFrame_03() {
		super();
		setTitle("使用网格组布局管理器");
		getContentPane().setLayout(new GridBagLayout());
		setBounds(100, 100, 500, 170);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		final JButton button = new JButton("A");
		final GridBagConstraints gridBagConstraints = new GridBagConstraints();
		gridBagConstraints.gridy = 0;// 起始点为第1行
		gridBagConstraints.gridx = 0;// 起始点为第1列
		gridBagConstraints.weightx = 10;// 第一列的分布方式为10%
		gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
		getContentPane().add(button, gridBagConstraints);

		final JButton button_1 = new JButton("B");
		final GridBagConstraints gridBagConstraints_1 = new GridBagConstraints();
		gridBagConstraints_1.gridy = 0;
		gridBagConstraints_1.gridx = 1;
		// 设置组件左侧的最小距离
		gridBagConstraints_1.insets = new Insets(0, 5, 0, 0);
		gridBagConstraints_1.weightx = 20;// 第一列的分布方式为20%
		gridBagConstraints_1.fill = GridBagConstraints.HORIZONTAL;
		getContentPane().add(button_1, gridBagConstraints_1);

		final JButton button_2 = new JButton("C");
		final GridBagConstraints gridBagConstraints_2 = new GridBagConstraints();
		gridBagConstraints_2.gridy = 0;// 起始点为第1行
		gridBagConstraints_2.gridx = 2;// 起始点为第3列
		gridBagConstraints_2.gridheight = 2;// 组件占用两行
		gridBagConstraints_2.insets = new Insets(0, 5, 0, 0);
		gridBagConstraints_2.weightx = 30;// 第一列的分布方式为30%
		// 同时调整组件的宽度和高度
		gridBagConstraints_2.fill = GridBagConstraints.BOTH;
		getContentPane().add(button_2, gridBagConstraints_2);

		final JButton button_3 = new JButton("D");
		final GridBagConstraints gridBagConstraints_3 = new GridBagConstraints();
		gridBagConstraints_3.gridy = 0;
		gridBagConstraints_3.gridx = 3;
		gridBagConstraints_3.gridheight = 4;
		// 设置组件左侧和右侧的最小距离
		gridBagConstraints_3.insets = new Insets(0, 5, 0, 5);
		gridBagConstraints_3.weightx = 40;// 第一列的分布方式为40%
		gridBagConstraints_3.fill = GridBagConstraints.BOTH;
		getContentPane().add(button_3, gridBagConstraints_3);

		final JButton button_4 = new JButton("E");
		final GridBagConstraints gridBagConstraints_4 = new GridBagConstraints();
		gridBagConstraints_4.gridy = 1;
		gridBagConstraints_4.gridx = 0;
		gridBagConstraints_4.gridwidth = 2;// 组件占用两列
		// 设置组件上方的最小距离
		gridBagConstraints_4.insets = new Insets(5, 0, 0, 0);
		// 只调整组件的宽度
		gridBagConstraints_4.fill = GridBagConstraints.HORIZONTAL;
		getContentPane().add(button_4, gridBagConstraints_4);

		final JButton button_5 = new JButton("F");
		final GridBagConstraints gridBagConstraints_5 = new GridBagConstraints();
		gridBagConstraints_5.gridy = 2;// 起始点为第3行
		gridBagConstraints_5.gridx = 0;// 起始点为第1列
		gridBagConstraints_5.insets = new Insets(5, 0, 0, 0);
		gridBagConstraints_5.fill = GridBagConstraints.HORIZONTAL;
		getContentPane().add(button_5, gridBagConstraints_5);

		final JButton button_6 = new JButton("G");
		final GridBagConstraints gridBagConstraints_6 = new GridBagConstraints();
		gridBagConstraints_6.gridy = 2;
		gridBagConstraints_6.gridx = 1;
		gridBagConstraints_6.gridwidth = 2;// 组件占用两列
		gridBagConstraints_6.gridheight = 2;// 组件占用两行
		gridBagConstraints_6.insets = new Insets(5, 5, 0, 0);
		gridBagConstraints_6.fill = GridBagConstraints.BOTH;// 只调整组件的高度
//		gridBagConstraints_6.fill = GridBagConstraints.VERTICAL;// 只调整组件的高度
//		gridBagConstraints_6.ipadx = 30;// 增加组件的首选宽度
//		gridBagConstraints_6.anchor = GridBagConstraints.EAST;// 显示在东方
		getContentPane().add(button_6, gridBagConstraints_6);

		final JButton button_7 = new JButton("H");
		final GridBagConstraints gridBagConstraints_7 = new GridBagConstraints();
		gridBagConstraints_7.gridy = 3;
		gridBagConstraints_7.gridx = 0;
		gridBagConstraints_7.insets = new Insets(5, 0, 0, 0);
		gridBagConstraints_7.fill = GridBagConstraints.HORIZONTAL;
		getContentPane().add(button_7, gridBagConstraints_7);
		//
	}

}

运行本例,将得到如图所示的窗体。组件C占用两行,填充方 式为全部填充;组件D占用4行,填充方式为全部填充;组件E占用两 列,填充方式为水平填充;组件G占用两行两列,填充方式为全部填充。

使用网格组布局管理器
使用网格组布局管理器

如果将组件G的填充方式改为垂直填充,并在水平方向上将组件的 首选宽度增加30像素,将显示位置设为东方,修改后组件G的实现代码如下:

布局管理器代码
修改组件G设置后的效果
修改组件G设置后的效果

发表评论