Swing开发中经常需要使用各种布局管理器来实现UI界面的各种布局,较为常用有:BorderLayout、FlowLayout、GridLayout、BoxLayout、CardLayout、GridBagLayout。
当Swing提供的布局管理器不能满足界面需求时,还可以自定义一套布局来处理特殊的UI界面。
BorderLayout布局管理器
官方文档介绍
----begin 官方文档开始----
这是一个布置容器的边框布局,它可以对容器组件进行安排,并调整其大小,使其符合下列五个区域:北、南、东、西、中。每个区域最多只能包含一个组件,并通过相应的常量进行标识:NORTH、SOUTH、EAST、WEST、CENTER。当使用边框布局将一个组件添加到容器中时,要使用这五个常量之一,例如:
Panel p = new Panel();
p.setLayout(new BorderLayout());
p.add(new Button("Okay"), BorderLayout.SOUTH);
为了方便起见,BorderLayout 将缺少字符串说明的情况解释为常量 CENTER:
Panel p2 = new Panel();
p2.setLayout(new BorderLayout());
p2.add(new TextArea()); // 等同于 p.add(new TextArea(), BorderLayout.CENTER);
此外,
BorderLayout
支持相对定位常量
PAGE_START
、
PAGE_END
、
LINE_START
和
LINE_END
。在
ComponentOrientation
设置为
ComponentOrientation.LEFT_TO_RIGHT
的容器中,这些常量分别映射到
NORTH
、
SOUTH
、
WEST
和
EAST
。
为了与以前的版本兼容,
BorderLayout
还包括相对定位常量
BEFORE_FIRST_LINE
、
AFTER_LAST_LINE
、
BEFORE_LINE_BEGINS
和
AFTER_LINE_ENDS
。这些常量分别等同于
PAGE_START
、
PAGE_END
、
LINE_START
和
LINE_END
。为了与其他组件使用的相对定位常量一致,应优先使用后一组常量。
将绝对定位常量与相对定位常量混合会产生无法预料的结果。如果两种类型的常量都使用,则优先采用相对常量。例如,如果同时使用
NORTH
和
PAGE_START
常量在方向性为
LEFT_TO_RIGHT
的容器中添加组件,则只体现
PAGE_START
布局。
注:目前,在 Java 2 Platform v1.2 中,
BorderLayout
不支持垂直方向。不考虑容器的
ComponentOrientation
上
isVertical
设置。
根据其首选大小和容器大小的约束 (constraints) 对组件进行布局。
NORTH
和
SOUTH
组件可以在水平方向上拉伸;而
EAST
和
WEST
组件可以在垂直方向上拉伸;
CENTER
组件可同时在水平和垂直方向上拉伸,从而填充所有剩余空间。
以下是一个使用
BorderLayout
布局管理器的例子,它对一个 applet 中的五个按钮进行布局:

此 applet 的代码如下:
import java.awt.*;
import java.applet.Applet;
public class buttonDir extends Applet {
public void init() {
setLayout(new BorderLayout());
add(new Button("North"), BorderLayout.NORTH);
add(new Button("South"), BorderLayout.SOUTH);
add(new Button("East"), BorderLayout.EAST);
add(new Button("West"), BorderLayout.WEST);
add(new Button("Center"), BorderLayout.CENTER);
}
}
----end 官方文档结束----
使用时需要注意的问题
1.BorderLayout在布局”北、南、东、西、中“时这个顺序不是随便写的,而是BorderLayout先布局哪个方位的顺序,是一个优先级的顺序。
2.”北、南、东、西、中“的优先级顺序可以简化为”北南、东西、中“。
3.虽然”北、南“之间有优先级,”东、西“之间也有优先级,但是它们之间的优先级非常弱,尽量不要依赖这个优先级。
例如以下代码是不合适的:
JPanel panel = new JPanel(new BorderLayout());
JPanel westPanel = new JPanel();
panel.add(westPanel, BorderLayout.WEST);
JPanel eastPanel = new JPanel();
panel.add(eastPanel, BorderLayout.EAST);
这样的代码在panel宽度不够的情况下,eastPanel会覆盖westPanal并且不彻底。什么叫不彻底?就是westPanel被eastPanel覆盖的部分如果有组件,那么组件会显示在屏幕上!
所以应该改为下面这样:
JPanel panel = new JPanel(new BorderLayout());
JPanel westPanel = new JPanel();
panel.add(westPanel, BorderLayout.WEST);
JPanel eastPanel = new JPanel();
panel.add(eastPanel, BorderLayout.CENTER);
由于中部的等级低于北部,所以eastPanel会覆盖westPanal并且不会出现上面提到的覆盖不彻底的情况。
4.两个组件不要重复添加到BorderLayout布局容器中的同一个位置。
如果两个组件被重复添加到一个BorderLayout布局容器中的同一个位置,如以下代码:
JPanel panel=new JPanel(new BorderLayout());
panel.add(component1,BorderLayout.EAST);
panel.add(component2,BorderLayout.EAST);
那么这样的代码并不会导致component1替换掉component2,而是component2附着在component1上面,如果窗口component1和component2的PreferredSize被设置为一样的大小,那么一般界面上是看不出来有任何问题的,但如果窗体放大或者拉伸时,就可以偶尔看见component1了。
所以这样的代码一定要杜绝出现,应该改成下面这样。
JPanel panel=new JPanel(new BorderLayout());
panel.add(component1,BorderLayout.EAST);
***//其他业务代码
panel.remove(component1);
panel.add(component2,BorderLayout.EAST);
5.布局特点
BorderLayout布局管理器部分使用组件自己的preferredSize,如南部和北部只能设置高度,东部和西部只能设置宽度,中部则不能设置任何宽高。
FlowLayout布局管理器
官方文档介绍
----begin 官方文档开始----
流布局用于安排有向流中的组件,这非常类似于段落中的文本行。流的方向取决于容器的
componentOrientation
属性,它可能是以下两个值中的一个:
-
ComponentOrientation.LEFT_TO_RIGHT
-
ComponentOrientation.RIGHT_TO_LEFT
流布局一般用来安排面板中的按钮。它使得按钮呈水平放置,直到同一条线上再也没有适合的按钮。线的对齐方式由
align
属性确定。可能的值为:
-
LEFT
-
RIGHT
-
CENTER
-
LEADING
-
TRAILING
例如,以下图片显示了使用流布局管理器(它的默认布局管理器)来定位三个按钮的 applet:
以下是此 applet 的代码:
import java.awt.*;
import java.applet.Applet;
public class myButtons extends Applet {
Button button1, button2, button3;
public void init() {
button1 = new Button("Ok");
button2 = new Button("Open");
button3 = new Button("Close");
add(button1);
add(button2);
add(button3);
}
}
----end 官方文档结束----
FlowLayout使用起来非常简单,而且JPanel的默认布局就是FlowLayout。
FlowLayout布局构造参数主要有三个:
public FlowLayout(int align, int hgap,int vgap)
创建一个新的流布局管理器,它具有指定的对齐方式以及指定的水平和垂直间隙。
参数:
align - 对齐值,align参数的值必须是以下值之一:FlowLayout.LEFT、FlowLayout.RIGHT、FlowLayout.CENTER、FlowLayout.LEADING 或 FlowLayout.TRAILING。
hgap - 组件之间以及组件与 Container 的边之间的水平间隙。
vgap - 组件之间以及组件与 Container 的边之间的垂直间隙。
使用时需要注意的问题
1.hgap和vgap其实不应该被理解成组件与组件的间隙,而应该是组件前面应该要留出的间隙。
可能你要的效果图是这样的:
于是你写了下面这样的代码:
public class LayoutTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 200);
frame.setLocationRelativeTo(null);
frame.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
frame.add(new JButton("btn1"));
frame.add(new JButton("btn1"));
frame.add(new JButton("btn1"));
frame.add(new JButton("btn1"));
frame.setVisible(true);
}
}
运行这段代码的效果却是这样的:
没办法,如果你不需要再最前面留间隙的话,你只能把代码改成下面这样:
public class LayoutTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 200);
frame.setLocationRelativeTo(null);
frame.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 10));
frame.add(new JButton("btn1"));
frame.add(Box.createHorizontalStrut(10));
frame.add(new JButton("btn1"));
frame.add(Box.createHorizontalStrut(10));
frame.add(new JButton("btn1"));
frame.add(Box.createHorizontalStrut(10));
frame.add(new JButton("btn1"));
frame.setVisible(true);
}
}
2.FlowLayout在布局组件时,如果容器的大小不够,组件会被显示一部分,有被切掉的感觉。
如图:
如果你不想组件在窗口缩小时被切掉的话,建议使用滚动条:
当然,你也可以使用其他布局代替FlowLayout以避免组件被切掉的效果。
3.布局特点
FlowLayout布局管理器完全使用组件自己的preferredSize,FlowLayout只负责管理组件摆放的位置。
GridLayout布局管理器
官方文档介绍
----begin 官方文档开始----
GridLayout 类是一个布局处理器,它以矩形网格形式对容器的组件进行布置。容器被分成大小相等的矩形,一个矩形中放置一个组件。例如,下面是一个将六个按钮布置到三行两列中的 applet:
import java.awt.*;
import java.applet.Applet;
public class ButtonGrid extends Applet {
public void init() {
setLayout(new GridLayout(3,2));
add(new Button("1"));
add(new Button("2"));
add(new Button("3"));
add(new Button("4"));
add(new Button("5"));
add(new Button("6"));
}
}
如果容器的 ComponentOrientation 属性是水平从左到右的,则上述示例生成图 1 中所示的输出。如果容器的 ComponentOrientation 属性是水平从右到左的,则该示例生成图 2 所示的输出。
通过构造方法或 setRows 和 setColumns 方法将行数和列数都设置为非零值时,指定的列数将被忽略。列数通过指定的行数和布局中的组件总数来确定。因此,例如,如果指定了三行和两列,在布局中添加了九个组件,则它们将显示为三行三列。仅当将行数设置为零时,指定列数才对布局有效。
----end 官方文档结束----
GridLayout布局的构造方法主要有4个参数:
public GridLayout(int rows, int cols,int hgap,int vgap)
创建具有指定行数和列数的网格布局。给布局中的所有组件分配相等的大小。
此外,将水平和垂直间距设置为指定值。水平间距将置于列与列之间。将垂直间距将置于行与行之间。
rows 和 cols 中的一个可以为零(但不能两者同时为零),这表示可以将任何数目的对象置于行或列中。
所有 GridLayout 构造方法都服从这一规定。
参数:
rows - 表示最少要摆放多少行,如果rows为0或负数,则表示行数不受限制
cols - 表示最少要摆放多少列,如果cols为0或负数,则表示列数不受限制
hgap - 组件之间水平间距,不会影响到组件和容器之间的间距。
vgap - 组件之间垂直间距
使用时需要注意的问题
1.如果添加组件时多添加了组件,则会开辟新列而不受cols限制。
如你设置了1行2列,添加了三个组件:
public class LayoutTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 200);
frame.setLocationRelativeTo(null);
JPanel panel = new JPanel(new GridLayout(1, 2, 10, 10));
frame.setContentPane(panel);
JButton button = new JButton("btn1");
button.setBorder(BorderFactory.createLineBorder(Color.RED));
panel.add(button);
button = new JButton("btn1");
button.setBorder(BorderFactory.createLineBorder(Color.RED));
panel.add(button);
button = new JButton("btn1");
button.setBorder(BorderFactory.createLineBorder(Color.RED));
panel.add(button);
frame.setVisible(true);
}
}
运行结果却出现1行3列:
2.如果出现像素不能均分,则会在将多余空间留作间隙,分配到容器的两侧。
如上图就出现了左右两侧各自留有1个像素。
3.布局特点
GridLayout布局管理器完全不使用组件自己的preferredSize,在任何情况下每个组件的大小都是一致的。
BoxLayout布局管理器
BoxLayout官方完整示例网址是: http://java.sun.com/docs/books/tutorial/uiswing/layout/box.html,非常详细,比API文档详细了N倍,就是有一点不好,是英文的。 英文不好的人,只能用金山词霸慢慢看了。
官方文档介绍
----begin 官方文档开始----
允许垂直或水平布置多个组件的布局管理器。这些组件将不包装,因此举例来说,垂直排列的组件在重新调整框架的大小时仍然被垂直排列。
以下文本是对此图像的描述。
用水平组件和垂直组件的不同组合嵌套多面板的作用类似于 GridBagLayout,但没那么复杂。该图显示了两个水平排列的面板,每个面板都包含 3 个垂直排列的组件。
BoxLayout 管理器是用 axis 参数构造的,该参数指定了将进行的布局类型。有四个选择:
X_AXIS:从左到右水平布置组件。
Y_AXIS:从上到下垂直布置组件。
LINE_AXIS:根据容器的 ComponentOrientation 属性,按照文字在一行中的排列方式布置组件。如果容器的 ComponentOrientation 表示水平,则将组件水平放置,否则将它们垂直放置。对于水平方向,如果容器的 ComponentOrientation 表示从左到右,则组件从左到右放置,否则将它们从右到左放置。对于垂直方向,组件总是从上到下放置的。
PAGE_AXIS:根据容器的 ComponentOrientation 属性,按照文本行在一页中的排列方式布置组件。如果容器的 ComponentOrientation 表示水平,则将组件垂直放置,否则将它们水平放置。对于水平方向,如果容器的 ComponentOrientation 表示从左到右,则组件从左到右放置,否则将它们从右到左放置。对于垂直方向,组件总是从上向下放置的。
对于所有方向,组件按照将它们添加到容器中的顺序排列。
BoxLayout 试图按照组件的首选宽度(对于水平布局)或首选高度(对于垂直布局)来排列它们。对于水平布局,如果并不是所有的组件都具有相同的高度,则 BoxLayout 会试图让所有组件都具有最高组件的高度。
如果对于某一特定组件而言这是不可能的,则 BoxLayout 会根据该组件的 Y 调整值对它进行垂直调整。默认情况下,组件的 Y 调整值为 0.5,这意味着组件的垂直中心应该与其他 Y 调整值为 0.5 的组件的垂直中心具有相同 Y 坐标。
同样地,对于垂直布局,BoxLayout 试图让列中的所有组件具有最宽组件的宽度。如果这样做失败,则 BoxLayout 会根据这些组件的 X 调整值对它进行水平调整。对于 PAGE_AXIS 布局,基于组件的开始边水平调整。换句话说,如果容器的 ComponentOrientation 表示从左到右,则 X 调整值为 0.0 意味着组件的左边缘,否则它意味着组件的右边缘。
许多程序使用 Box 类,而不是直接使用 BoxLayout。Box 类是使用 BoxLayout 的轻量级容器。它还提供了一些帮助您很好地使用 BoxLayout 的便利方法。要获取您想要的排列,将组件添加到多个嵌套的 box 中是一种功能强大的方法。
----end 官方文档结束----
使用时需要注意的问题
。。。好累
,改天有兴致再写吧。 。。。未完待续。。。