目录

1. 流式布局管理器

2. 边界布局管理器

3. 网格布局管理器

4. 卡片布局管理器

5. 盒式布局管理器

6. 网格布袋布局管理器

7. 弹性布局管理器


       在Java图形用户界面系统中,容器中包含了组件,组件的布局是由布局管理器负责安排。布局管理器负责容器内组件的排列顺序、大小、位置,以及当窗口移动或调整后组件如何变化等。每个容器都有一个默认的的布局管理器,可以通过容器的setLayout()方法改变容器的布局管理器。Java平台提供了7种布局管理器:FlowLayout、BorderLayout、GridLayout、BoxLayout、CardLayout、SpringLayout、GridBagLayout和SpringLayout

1. 流式布局管理器

       流式布局管理器(FlowLayout)对容器中组件进行布局的方式是将组件从左到右逐个地安放在容器中的一行上,一行放满后就另起新的一行。

       FlowLayout的主要构造方法如下:

public FlowLayout();

public FlowLayout(int align);

public FlowLayout(int align, int hgap, int vgap);

    其中,参数align指定组件的对其方式,它是通过FlowLaout的常量指定的,取值有FlowLayout.LEFT、FlowLayout.RIGHT和FlowLayout.CENTER三种方式,分别表示左对齐、右对齐和居中;参数hgap和vgap设置组件的水平和垂直间距,默认的水平和垂直间距是5个单位。

【例1】流式布局管理器的使用。

import java.awt.Container;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class FlowLayoutDemo {
	public static void main(String[] args) {
		JFrame frame=new JFrame("流式布局");//创建窗口 
		frame.setSize(300,200);//设置窗口的大小
		//设置窗口的布局管理器为流式布局管理器
		frame.setLayout(new FlowLayout(FlowLayout.LEFT,20,30));
		Container contentPane=frame.getContentPane();//获取窗口的内容窗格
		//创建三个按钮依次钮添加到窗口中
		contentPane.add(new JButton("确定"));
		contentPane.add(new JButton("取消"));
		contentPane.add(new JButton("关闭"));
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);	
	}
}

运行上述程序,显示结果如图1(2)所示,拖动窗口的边缘使窗口变窄,组件会自动换行,如图2所示。

(a)

(b)

图1. 流式布局管理器的示例1

2. 边界布局管理器

       边界布局管理器(BorderLayout)是顶层容器中内容窗格的默认布局管理器。每个由BorderLayout管理的容器被划分成北、南、西、东、中五个区域,在每个区域可以加入一个组件。

       BorderLayout的主要构造方法如下:

public BorderLayout();

public BorderLayout(int hgap, int vgap);

      其中,参数hgap和vgap用来设置组件的水平和垂直间距。BorderLayout提供了5个约束常量:BorderLayout.North、BorderLayout.South、BorderLayout.West、BorderLayout.East、BorderLayout.Center,分别用来表示容器的北部区域、南部区域、西部区域、东部区域、中部区域和中部区域。

【例2】边界布局管理器的使用。

import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.JButton;
import javax.swing.JFrame;
public class BorderLayoutDemo {
	public static void main(String[] args) {
		JFrame frame=new JFrame("边界布局"); //创建一个窗口
		frame.setSize(300,200);//设置窗口的大小
		frame.setLayout(new BorderLayout(10,10));//设置为边界布局管理器
		Container contentPane=frame.getContentPane();//获取窗口的内容窗格
		//创建五个按钮分别添加到窗口的北、南、西、东和中部
		contentPane.add(new JButton("北部"),BorderLayout.NORTH);
		contentPane.add(new JButton("南部"),BorderLayout.SOUTH);
		contentPane.add(new JButton("西部"),BorderLayout.WEST);
		contentPane.add(new JButton("东部"),BorderLayout.EAST);
		contentPane.add(new JButton("中部"),BorderLayout.CENTER);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
}

运行上述程序,显示结果如图2(a)所示。当使用边界布局管理器时,如果容器的大小发生变化,组件的大小也发生比变化,但是相对大小不变,如图2(b)所示。

(a)

(b)

图2. 边界布局管理器的使用示例

3. 网格布局管理器

       网格布局管理器(GridLayout)将容器空间划分为若干行乘若干列的矩形网格,每个单元格区域大小相同,组件依次放入其中,每个组件占据一个单元格。

       GridLayout的主要构造方法如下:

public GridLayout();

public GridLayout(int rows, int cols);

public GridLayout(int rows, int cols, int hgap, int vgap);

       其中,参数rows和cols分别指定网格的行数和列数,hgap和vgap分别所设置网格的水平间距和垂直间距,默认无间距。

【例3】网格布局管理器的使用。

import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class GridLayoutDemo {
	public static void main(String[] args) {
		JFrame frame=new JFrame("网格布局"); 
		//设置3行2列的网格布局管理器
		frame.setLayout(new GridLayout(3,2,1,1));
		Container contentPane=frame.getContentPane();//获取内容窗格
//创建5个按钮组件分别添加到窗口的不同单元格中
		contentPane.add(new JButton("单元格1"));
		contentPane.add(new JButton("单元格2"));
		contentPane.add(new JButton("单元格3"));
		contentPane.add(new JButton("单元格4"));
		contentPane.add(new JButton("单元格5"));
		contentPane.add(new JButton("单元格6"));
		//设置窗口的大小并显示
		frame.setSize(300,200);
		frame.setVisible(true);	
	}
}

运行上述程序,显示结果如图3(a)所示。如果只添加5个按钮组件,则显示的结果如图3(b)所示。

(a)

(b)

图3.  网格布局管理器的使用示例

4. 卡片布局管理器

       卡片布局管理器(CardLayout)提供了类似于管理一系列卡片一样管理容器内组件的功能,多个组件拥有一个显示空间,每一时刻只能显示其中的一个组件。

       CardLayout的主要构造方法如下:

public CardLayout();

public CardLayout(int hgap, int vgap);

       其中,参数hgap和vgap用来指定卡片水平和垂直间距,水平间距是指卡片的左右与边缘之间的距离,垂直间距是指卡片的上下与边缘之间的距离。

       CardLayout提供如下一些方法用来检索卡片:

方法功能描述
public void first(Container parent)显示容器中的第一张卡片
public void last(Container parent)显示容器中的最后一张卡片
public void previous(Container parent)显示容器中的前一张卡片
public void next(Container parent)显示容器中的后一张卡片
public void show(Container parent,String name)显示容器中指定名字的卡片

【例4】卡片布局管理器的使用。

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class CardLayoutDemo {
	public static void main(String[] args) {
		JFrame frame=new JFrame("卡片布局"); //创建一个窗口
		JPanel cardPanel=new JPanel(); //创建一个面板用来存储卡片
		CardLayout cardLayout=new  CardLayout(1,1);//创建卡片布局管理器
		cardPanel.setLayout(cardLayout);//设置面板为卡片布局管理器
		//创建4个按钮添加到卡片面板中
		cardPanel.add(new JButton("卡片1"));
		cardPanel.add(new JButton("卡片2"));
		cardPanel.add(new JButton("卡片3"));
		cardPanel.add(new JButton("卡片4"));
		//创建事件监听器对象
		ActionListener listener=new ActionListener() {
			//定义事件处理器
			public void actionPerformed(ActionEvent e) {
				String str=e.getActionCommand();
				switch(str) {
					case "第一张":
						cardLayout.first(cardPanel);;
						break;
					case "下一张":
						cardLayout.next(cardPanel);
						break;
					case "上一张":
						cardLayout.previous(cardPanel);
						break;
					case "最后一张":
						cardLayout.last(cardPanel);
						break;		
				}
			}
		};
		JPanel btnPanel=new JPanel(); //创建一个面板用来存储存按钮
		//创建4个按钮
		JButton button1=new JButton("第一张");
		JButton button2=new JButton("下一张");
		JButton button3=new JButton("上一张");
		JButton button4=new JButton("最后一张");
		//注册按钮的事件监听器对象
		button1.addActionListener(listener);
		button2.addActionListener(listener);
		button3.addActionListener(listener);
		button4.addActionListener(listener);
		//将按钮添加到btnPanel面板中
		btnPanel.add(button1);
		btnPanel.add(button2);
		btnPanel.add(button3);
		btnPanel.add(button4);
		//将卡片面板添加到窗口的中部
		frame.add(cardPanel,BorderLayout.CENTER);
		//将按钮面板添加到窗口的南部
		frame.add(btnPanel,BorderLayout.SOUTH);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		frame.setSize(400,300);
		frame.setVisible(true);
	}
}

运行上述程序,显示结果如图4(a)所示。点击“下一张”按钮显示结果如图4(b)所示,继续点击“下一张”按钮显示结果如图4(c)所示,点击“上一张”按钮又回到图(b)的结果,点击“最后一张”按钮显示结果如图4(d)所示。该例子中使用了事件处理机制,该内容将在后面的文章中详细描述。

(a)

(b)

(c)

(d)

图4. 卡片布局管理器的使用示例

5. 盒式布局管理器

       盒式布局管理器(BoxLayout)将容器中的组件按照水平方向排成一行或按照垂直方向排成一列。当组件排成一行时,每个组件可以有不同的宽度;当组件排成一列时,每个组件可以有不同的宽度。

        BoxLayout的构方法如下:

                                public BoxLayoutLayout(Container target, int axis);

     其中,参数target指明是为哪个容器设置此布局管理器;axis指明组件的排列方向,BoxLayout.X_AXIS、BoxLayout.Y_AXIS分别表示按水平方向排列和按垂直方向排列。

【例5】盒式布局管理器的使用。

import java.awt.BorderLayout;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BoxLayoutDemo {
	public static void main(String[] args) {
		JFrame frame=new JFrame("盒式布局");//创建窗口
		frame.setSize(300,200);//设置窗口的大小
		//创建一个面板,设置为垂直排列的盒式布局管理器
		JPanel vpanel=new JPanel();
		vpanel.setLayout(new BoxLayout(vpanel,BoxLayout.Y_AXIS));
        //创建3个按钮添加到vpanel面板中
		vpanel.add(new JButton("按钮1"));
		vpanel.add(new JButton("按钮2"));
		vpanel.add(new JButton("按钮3"));
		//创建另个面板,设置为水平排列的盒式布局管理器
		JPanel hpanel=new JPanel();
		hpanel.setLayout(new BoxLayout(hpanel,BoxLayout.X_AXIS));
        //创建3个按钮添加到hpanel面板中
		hpanel.add(new JButton("按钮4"));
		hpanel.add(new JButton("按钮5"));
		hpanel.add(new JButton("按钮6"));
		frame.add(vpanel,BorderLayout.CENTER);
		frame.add(hpanel,BorderLayout.SOUTH);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
}

运行上述程序,显示结果如图5所示,其中,按钮1、按钮2和按钮3垂直排列,按钮4、按钮5和按钮6水平排列。

图5. 盒式布局管理器的使用示例

6. 网格布袋布局管理器

       与网格布局管理器(GridLayout)类似,网格布袋布局管理器(GridBagLayout)也是将容器划分为若干个网格,不同之处在于,网格布袋布局管理器中的每个单元格的高度和宽度都可以不一样,每个组件可以占据一个或多个单元格,可以指定组件在网格中停靠的位置。利用网格布袋布局管理器可以构造更加复杂的用户界面。

        当将一个组件添加使用了网格布袋布局管理器的容器中时,需要指定该组件的位置、大小、缩放等约束条件,可以使用GridBagConstraints类的对象来存储这些约束。GridBagLayout只有一个默认的构造方法,可以使用GridBagLayout提供的方法setConstraints(Component comp,GridBagConstraints constraints)来设置组件在网格中的约束。

       GridBagConstraints类中的主要属性含义如下:

  • gridx和gridy:组件左上角所在的横坐标和纵坐标,坐标是从0开始,从容器的左上角算起。
  • gridwidth和gridheight:组件在网格张所占据的行数和列数,默认情况下它们的取值都为1。
  • weightx和weighty:当容器的大小发生变化时,组件在横向和纵向变化的增量值,取值为0时,组件的大小不发生变化。
  • fill:组件所处单元格的填充方式,取值有GridBagConstraints.NONE、GridBagConstraints.HORIZONTAL、GridBagConstraints.VERTICAL、GridBagConstraints.BOTH,其分别表示不填充、水平填充、垂直填充、水平和垂直填充。

【例6】利用网格布袋布局管理器设计一个如图6所示的界面,该界面包含10个单元格,其中,单元格1占据1行4列,单元格5占据2行1列,单元格9和10占据1行2列,单元格2、3、4、6、7、8占据1行1列。

图6. 单元格的划分

import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class GridBagLayoutDemo {
	public static void main(String[] args) {
		JFrame frame=new JFrame("网格布袋布局"); 
		frame.setSize(300,200);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Container contentPane=frame.getContentPane();
		GridBagLayout gl=new GridBagLayout();//创建一个网格布袋管理器
		contentPane.setLayout(gl);//设置窗口的布局为网格布袋管理器
		GridBagConstraints gc=new GridBagConstraints();//创建网格布袋约束
		int[] gx= {0,0,1,2,3,0,1,2,0,2};//定义组件的横坐标
		int[] gy= {0,1,1,1,1,2,2,2,3,3};//定义组件的纵坐标
		int[] gw= {4,1,1,1,1,1,1,1,2,2};//定义组件占据的行数
		int[] gh= {1,1,1,1,2,1,1,1,1,1};//定义组件占据的列数
		JButton button;
		String name; 
		//创建10个按钮分别放到窗口的相应网格中
		for(int i=0;i<gx.length;i++) {
			name="单元"+(i+1); //按钮的标题
			button=new JButton(name);//创建按钮
			gc.gridx=gx[i];//设定组件的横坐标
			gc.gridy=gy[i];//设定组件的纵坐标
			gc.gridwidth=gw[i];//设定组件占据的行数
			gc.gridheight=gh[i];//设定组件占据的列数
			gc.weightx=100;//设定组件的横向增量值
			gc.weighty=100;//设定组件的纵向增量值
			gc.fill=GridBagConstraints.BOTH;//设定组件的填充方式
			gl.setConstraints(button, gc);//设定组件的约束对象
			contentPane.add(button);
		}
		frame.setVisible(true);
	}
}

运行上述程序,显示结果如图7(a)所示,如果设置组件的横向和纵向增量的取值为0,则显示结果如图7(b)所示。

(a)

(b)

图7.  网格布袋布局管理器的使用示例

7. 弹性布局管理器

       弹性布局管理器(SpringLayout)是一种基于约束的布局管理器,可以通过设置组件之间的约束关系来控制它们的位置。使用弹性布局管理器的容器内的每一个组件或容器都对应一个约束,通过该约束定义组件或容器四条边的坐标位置来实现组件的布局。弹性布局管理器的主要特点是:当改变窗口大小时,自动调整组件的大小布满整个窗口,而组件之间的相对位置不变。

       弹性布局管理器主要涉及三个类:SpringLayout、SpringLayout.Constraints、Spring,分别表示布局管理器、约束和坐标距离。

       (1) SpringLayout

       SpringLayout表示一个布局管理器,通过该布局管理器可以获取组件或容器的约束对象。SpringLayout类提供的主要方法如下:

方法功能描述
SpringLayout.Constraints getConstraints(Component c)获取组件的约束对象
putConstraint(String e1, Component c1, int pad, String e2, Component c2)设置两个组件之间的约束,c1和c2是两个组件(其中的一个可可以是组件所在的容器),e1是组件c1需要参考的边,e2是组件c2需要参考的边,pad为两条边之间的距离,e1和e2的取值有SpringLayout.NORTH、SpringLayout.WEST、SpringLayout.SOUTH、SpringLayout.EAST,它们分别表示组件的北侧边、西侧边、南侧边和东侧边,当e2在e1的北侧或西侧时,pad为正数,当e2在e1的南侧或东侧时,pad为负数。

        (2) SpringLayout.Constraints

       SpringLayout.Constraints表示对组件和尺寸的约束,每个组件实例都对应着一个约束对象,通过该约束可以获取和设置组件四条边的坐标和宽度。SpringLayout.Constraints类提供的主要方法如下:

方法功能描述

setX(Spring x)

setY(Spring y)

设置组件左上角坐标的设置

setWidth(Spring w)设置组件的宽度
setHeight(Spring h)设置组件的高度
setConstraint(String edgeName,Spring s)组件指定边的坐标或长度设置

       (3) Spring

       Spring可以看作是在中SpringLayout中对距离的度量。一个Spring实例表示一段距离或长度,支持简单的算术运算,主要是由Spring提供的静态方法来实现的,常用的方法如下:

方法功能描述
static Spring constant(int pref)创建一个指定长度的Spring
static Spring sum(Spring s1,Spring s2)两个Spring相加,得到一个新的Spring
static Spring max(Spring s1,Spring s2)获取两个Spring中的较大者
static Spring scale(Spring s, float factor)对Spring进行缩放
static Spring width(Component c)获取组件的宽度所表示的Spring
static Spring height(Component c)获取组件的高度所表示的Spring

【例7】弹性布局管理器的使用。

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.Spring;
import javax.swing.SpringLayout;
public class SpringLayoutDemo {
	public static void main(String[] args) {
		JFrame frame=new JFrame("弹性布局");
		frame.setSize(300,200);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JPanel panel=new JPanel();//创建一个面板
		frame.setContentPane(panel);//设置窗口的内容窗格为所创建的面板
		//Container contentPane=frame.getContentPane();
		SpringLayout springLayout=new SpringLayout();//创建弹性布局管理器
		panel.setLayout(springLayout);//设置面板的布局为弹性布局
		
		//用户名标签组件
		JLabel label1=new JLabel("用户名:");
		panel.add(label1);
		SpringLayout.Constraints label1Cons=                        
                          springLayout.getConstraints(label1);
		label1Cons.setX(Spring.constant(20));//设置横坐标为20
		label1Cons.setY(Spring.constant(20));//设置纵坐标为20
		
		//用户名文本框组件
		JTextField textField=new JTextField();
		panel.add(textField);
		SpringLayout.Constraints textFieldCons=
                         springLayout.getConstraints(textField);
		//西侧边:到用户名标签组件东侧边的距离为10
		textFieldCons.setX(Spring.sum(
            label1Cons.getConstraint(SpringLayout.EAST), Spring.constant(10)));
		//北侧边:到面板北侧边的距离为20
		springLayout.putConstraint(SpringLayout.NORTH, textField, 20, 
                                   SpringLayout.NORTH, panel);
		//东侧边:到面板东侧边的距离为50
		springLayout.putConstraint(SpringLayout.EAST, textField, -50, 
                                   SpringLayout.EAST, panel);
		
		//密码标签组件
		JLabel label2=new JLabel("密    码:");
		panel.add(label2);
		SpringLayout.Constraints label2Cons=
                                 springLayout.getConstraints(label2);
		label2Cons.setX(Spring.constant(20));//设置横坐标为20
		//北侧边距离标签组件1南侧边的距离为20
		springLayout.putConstraint(SpringLayout.NORTH, label2, 20, 
                                   SpringLayout.SOUTH, label1);
		
		//口令域输入组件
		JPasswordField passwordField=new JPasswordField();
		panel.add(passwordField);
		//北侧边:到用户名文本框组件南侧边的距离为20
		springLayout.putConstraint(SpringLayout.NORTH, passwordField, 20, 
                                   SpringLayout.SOUTH, textField);
		//西侧边:到密码标签组件东侧边的距离为10
		springLayout.putConstraint(SpringLayout.WEST, passwordField, 10, 
                                   SpringLayout.EAST, label2);
		//东侧边:到面板东侧边的距离为50
		springLayout.putConstraint(SpringLayout.EAST, passwordField, -50, 
                                   SpringLayout.EAST, panel);
		
		//注册按钮组件
		JButton button1=new JButton("注册");
		panel.add(button1);
		//北侧边:到口令域输入组件南侧边的距离为20
		springLayout.putConstraint(SpringLayout.NORTH, button1, 20, 
                                   SpringLayout.SOUTH, passwordField);
		
	    //重置按钮组件	
		JButton button2=new JButton("重置");
		panel.add(button2);
		//北侧边:到口令域输入组件南侧边的距离为20
		springLayout.putConstraint(SpringLayout.NORTH, button2, 20, 
                                   SpringLayout.SOUTH, passwordField);
		//东侧边:到面板东侧边的距离为50
		springLayout.putConstraint(SpringLayout.EAST, button2, -50, 
                                   SpringLayout.EAST, panel);
		//西侧边:到注册按钮组件的距离为20
		springLayout.putConstraint(SpringLayout.EAST, button1, -20, 
                                  SpringLayout.WEST, button2);
		frame.setVisible(true);
	}
}

运行上述程序,显示结果如图8(a)所示。拖拽窗口使其宽度和高度增大,显示结果如图8(b)所示,从该图可以看出,随着宽度的增加,文本框组件和口令输入组件的宽度也随之增加,这是因为设定它们的东侧边与其所在面板的东侧边的相对距离为50,随着窗口宽度的增加,这个距离保持不变;由于没有设置组件南侧边与面板南侧边的相对距离,所以,随着窗口高度的增加,组件与窗口之间的距离也在增加。

(a)

(b)

图8. 弹性布局管理器的使用示例

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐