5、Java-Swing常用布局管理器
应用布局管理器都属于相对布局,各组件位置可随界面大小而相应改变,不变的只是其相对位置,布局管理器比较难以控制,一般只在界面大小需要改是才用,但即使这样,为了操作方便,也只是在大的模块下用布局管理器,在一些小的模块下还是用绝对布局。在一些没要求界面大小改变的窗口,一般采用绝对布局比较容易,但对于后期的修改来说比较麻烦。
5.1、 BorderLayout
这种布局管理器分为东、南、西、北、中心五个方位。北和南的组件可以在水平方向上拉伸;而东和西的组件可以在垂直方向上拉伸;中心的组件可同时在水平和垂直方向上同时拉伸,从而填充所有剩余空间。在使用BorderLayout的时候,如果容器的大小发生变化,其变化规律为:组件的相对位置不变,大小发生变化。例如容器变高了,则North、South 区域不变,West、Center、East区域变高;如果容器变宽了,West、East区域不变,North、Center、South区域变宽。不一定所有的区域都有组件,如果四周区域(West、East、North、South区域)没有组件,则由Center区域去补充,但是如果 Center区域没有组件,则保持空白。BorderLayout是RootPaneContainer(JInternalFrame、JDialog、JFrame、JWindow)的默认布局管理器。
示例:
1 import java.awt.*;
2 public class buttonDir{
3 public static void main(String args[]){
4 Frame f = new Frame("BorderLayout");
5 f.setLayout(new BorderLayout());
6 f.add("North", new Button("North");
7 //第一个参数表示把按钮添加到容器的North区域
8 f.add("South", new Button("South");
9 //第一个参数表示把按钮添加到容器的South区域
10 f.add("East", new Button("East");
11 //第一个参数表示把按钮添加到容器的East区域
12 f.add("West", new Button("West");
13 //第一个参数表示把按钮添加到容器的West区域
14 f.add("Center", new Button("Center");
15 //第一个参数表示把按钮添加到容器的Center区域
16 f.setSize(200,200);
17 f.setVisible(true);
18 }
19 }
5.2、FlowLayout
该布局称为流式布局管理器,是从左到右,中间放置,一行放不下就换到另外一行。一行能放置多少组件取决于窗口的宽度。默认组件是居中对齐,可以通过FlowLayout(intalign)函数来指定对齐方式,默认情况下是居中(FlowLayout.CENTER)。FlowLayout为小应用程序(Applet)和面板(Panel)的默认布局管理器。其构造函数示例为:
FlowLayout() //生成一个默认的流式布局,组件在容器里居中,每个组件之间留下5个像素的距离。
FlowLayout(int alinment) //可以设定每行组件的对齐方式。
FlowLayout(int alignment , int horz , int vert) //设定对齐方式并设定组件水平和垂直的距离。
当容器的大小发生变化时,用FlowLayout管理的组件会发生变化。其变化规律是:组件的大小不变,但是相对位置会发生变化。
5.3、CardLayout
这种布局管理器能够帮助用户处理两个以至更多的成员共享同一显示空间,它把容器分成许多层,每层的显示空间占据整个容器大小,但是每层只允许放置一个组件,当然每层都可以利用Panel来实现复杂的用户界面。CardLayout就象一副叠得整整齐齐的扑克牌一样,有54张牌,但是你只能看见最上面的一张牌,一张牌就相当于布局管理器中的一层。 所有的组件像卡片一样叠在一起,每时每刻都只能显示其中一张卡片。CardLayout常用到切换界面。例如,点击App的Menu之后或者某个Button之后,主界面会切换到另外一个界面,这个时候就需要CardLayout。其实现过程如下:
首先,定义面板,为个个面板设置不同的布局,并根据需要在每个面板中放置组件:
panelOne.setLayout(new FlowLayout); panelTwo.setLayout(new GridLayout(2,1));
再设置主面板: CardLayout card = new CardLayout(); panelMain.setLayout(card);
下一步将开始准备好的面板添加到主面板: panelMain.add("red panel",panelOne); panelMain.add("blue panel",panelOne);
add()方法带有两个参数,第一个为String类型用来表示面板标题,第二个为Panel对象名称。
完成以上步骤以后,必须给用户提供在卡片之间进行选择的方法。一个常用的方法是每张卡片都包含一个按钮。通常用来控制显示哪张面板。
actionListener被添加到按钮。actionPerformed()方法可定义显示哪张卡片:
card.next(panelMain); //下一个
card.previous(panelMain); //前一个 card.first(panelMain); //第一个 card.last(panelMain); //最后一个 card.show(panelMain,"red panel"); //特定面板
5.4、GridLayout
这种布局是网格式的布局,窗口改变的时候,组件的大小也会随之改变。每个单元格的大小一样,而且放置组件时,只能从左到右、由上到下的顺序填充,用户不能任意放置组件。如果改变大小, GridLayout将相应地改变每个网格的大小,以使各个网格尽可能地大,占据Container容器全部的空间。
用构造函数划分出网格的行数和列数, new GridLayout(行数,列数);
构造函数里的行数和列数能够有一个为零,但是不能都为零。当容器里增加控件时候,容器内将向0的那个方向增长。例如,如果是如下语句:
GridLayout layout= new GridLayout(0,1);
//在增加控件时,会保持一个列的情况下,不断把行数增长.
java.awt.GridBagConstraints 中的insets(0,0,0,0)的参数具体指的是:规定一个控件显示区的空白区。
如果控件显示的inset为(10,5,20,0),那么控件到显示区北边距离为10,西边为5,南边为20,东边为0控件会比显示区小。
如果inset为负,控件会超出显示区,使容器中各个组件呈网格状布局,平均占据容器的空间。当所有组件大小相同时用此布局。其构造函数为:
GridLayout() GridLayout(int row,int col) GridLayout(int row,int col,int horz,int vert)
5.5、BoxLayout
BoxLayout布局能够允许将控件按照X轴(从左到右)或者Y轴(从上到下)方向来摆放,而且沿着主轴能够设置不同尺寸。 构造BoxLayout对象时,有两个参数,例如:
Public BoxLayout(Container target,int axis);
Targe参数是表示当前管理的容器,axis是指哪个轴,有两个值:BoxLayout.X_AXIS和BoxLayout.Y_AXIS。
示例代码如下:
1 JPanel jpanel=new JPanel();
2
3 Jpanel.setLayout(new BoxLayout(jpanel,BoxLayout.Y_AXIS);
4
5 TextArea testArea=new TextArea(4,20);
6
7 JButton button=new JButton(“this is a button”);
8
9 jpanel.add(testArea);
10
11 jpanel.add(button);
//容纳testArea和button的容器,对他们沿Y轴(从上往下)放置,并且文本域和按纽左对齐,也就是两个控件的最左端在同一条线上。
1 testArea.setAlignmentX(Component.LEFT_ALIGNMENT);
2
3 button. setAlignmentX(Component.LEFT_ALIGNMENT);
//容纳testArea和button的容器,对他们采用沿Y轴(从上往下)放置,并且文本域最左端和按纽的最右端在同一条线上。
1 testArea.setAlignmentX(Component.LEFT_ALIGNMENT);
2
3 button. setAlignmentX(Component.RIGHT_ALIGNMENT);
setAlignmentX(left,right)只有在布局是BoxLayout.Y_AXIS才效,而setAlignmentY(top,button)在布局为BoxLayout.X_AXIS才效果。
组件对齐一般来说: 所有top-to-bottom BoxLayout object 应该有相同的 X alignment。 所有left-to-right Boxlayout应该有相同的 Y alignment setAlignmentX 和setAlignmentY 可以实现对齐。
5.6、GridBagLayout
可以完成复杂的布局,而且IDE对它有足够的支持,是一个很强大的Layout。不过它过于复杂,在此布局中,组件大小不必相同。可以采用以下代码容器获得一个GridBagLayout:
GridBagLayout gb=new GridBagLayout(); ContainerName.setLayout(gb);
要使用网格包布局,还必须有其一个辅助类,GridBagContraints。它包含GridBagLayout类用来定位及调整组件大小所需要的全部信息。使用步骤如下:
1) 创建网格包布局的一个实例,并将其定义为当前容器的布局管理器. 2) 创建GridBagContraints的一个实例 3) 为组件设置约束. 4) 通过方法统治布局管理器有关组件及其约束等信息 5) 将组件添加到容器. 6) 对各个将被显示的组件重复以上步骤.
GridBagContraints类的成员变量列表如下:
1) gridx,gridy 指定组件放在哪个单元中。其值应该设为常数CridBagConstraints.RELATIVE 。然后按标准顺序将组件加入网格包布局。从左到右,从上到下。 2) gridwidth,gridheight 指定组件将占用几行几列 3) weightx,weighty 指定在一个GridBagLayout中应如何分配空间。缺省为0。 4) ipadx,ipady 指定组件的最小宽度和高度。可确保组件不会过分收缩。 5) fill 指定在单元大于组件的情况下,组件如何填充此单元,缺省为组件大小不变,以下为静态数据成员列表,它们是fill变量的值。 GridBagConstraints.NONE 不改变组件大小 GridBagConstraints.HORIZONTAL 增加组件宽度,使其水平填充显示区域 GridBagConstraints.VERTICAL 增加组件高度,使其垂直填充显示区域 GridBagConstraints.BOTH 使组件填充整个显示区域 6) anchor 如果不打算填充可以通过anchor指定将组件放置在单元中的位置,缺省为将其放在单元的中部。可使用以下静态成员: GridBagConstraints.CENTER GridBagConstraints.NORTH GridBagConstraints.EAST GridBagConstraints.WEST GridBagConstraints.SOUTH GridBagConstraints.NORTHEAST GridBagConstraints.SOUTHEAST GridBagConstraints.NORTHWEST GridBagConstraints.SOUTHWEST 使用setConstraints()方法可以设置各组件约束。
GridBagLayout是是在GridLayout的基础上发展起来的,是五种布局策略中使用最复杂,功能最强大的一种,它是在GridLayout的基础上发展起来的。因为GridBagLayout中每个网格都相同大小并且强制组件与网格大小相同,使得容器中的每个组件也都是相同的大小,显得很不自然,而且组件假如容器中必须按照固定的行列顺序,不够灵活。在GridBagLayout中,可以为每个组件指定其包含的网格个数,组件可以保留原来的大小,可以以任意顺序随意地加入容器的任意位置,从而实现真正自由地安排容器中每个组件的大小和位置。
变量名 | 有效值 | 应用范围 | 定义 |
---|---|---|---|
anchor | CENTER EAST NORTH NORTHEAST SOUTH SOUTHWEST WEST | 组件 | 组件在网格中排放的位置 |
fill | BOTH HORIZONTAL VERTICAL NONE | 组件 | 组件填充网格的方式 |
gridx,gridy | RELATIVE 整数X,Y值 | 组件和显示区 | 组件的左上角网格的位置 |
gridheight gridwidth | 1 RELATIVE REMAINDER 宽,高度整数值 | 显示区 | 网格单元中组件显示区所占的高度和宽度 |
Insets | (0,0,0,0) | 组件和显示区 | 外部填充 |
ipadx,ipady | 0 | 组件和显示区 | 内部填充 |
public GridBagConstraints(int gridx, int gridy,int gridwidth, int gridheight,double weightx, double weighty,int anchor, int fill,Insets insets, int ipadx, int ipady),
GridBagConstraints 功能全面,内置了很多参数比如 anchor 描点,ipadx 内部填充, Weighty 指定如何分布额外的水平空间等等。所以当添加一个控件时,往往需要设置GridBagConstraints 很多参数才能达到效果,例如:
GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.ipadx = 3; gridBagConstraints.insets = new java.awt.Insets(3, 0, 3, 0); pnlContent.add(btn, gridBagConstraints)
上面几个常用Layout中GridBagConstraints的功能是最强的,不过他们之间没有什么可比性,根据不同的需求选择布局更能清晰反映布局带来的便捷式与高效性。到目前为止,我们知道GridBagConstraints可以较好地完成复杂的Layout,算是"功能全面“,但是它有缺点。
5.7、TableLayout
这种管理器把容器划分为行和列,就像是电子表格中的单元格。Tablelayouot把行和列交叉的每一个格子称为基本的单元格(cell)。组件被添加到容器划分好的单元格中。当容器发生改变(伸缩)时,单元格也随之伸缩,装载在单元格里的组件也相应的会进行伸缩。
以下图为例:此容器被分为4行5列。由图可看出,每一列的宽度并不是固定的,也不是平均宽度的。同理每一行的高度也不是均分的,可以按照实际情况进行分配列的宽度和行的高度。组件可以放在容易的一个cell单元格中,也可以占几个单元格。在单元格中,行和列都是从0开始计数。Row0表示第1行,col0表示第1列。
在使用之前,先给出TableLayout API:
TableLayout的官网(里面有很多例子):
http://www.clearthought.info/sun/products/jfc/tsc/articles/tablelayout/Simple.html
其实学习的另外的一种重要的方法就是多去官网里面,官网的资料是十分全面。
TableLayout行列的分配
一般来说,创建tablelayout要先设定行和列。定义一个double类型的二维数组size[][]。Java代码:
double size[][] ={{100, 0.50, 0.20, TableLayout.FILL, 200, TableLayout.FILL}, {TableLayout.FILL}};
在上面的代码中,size[0]中存放的是列的宽度,size[1]中存放的是行的高度;数组中的整数表示该单元格的宽度或高度为多少像素,小数表示该单元格的宽度或高度为剩余空间的百分之多少,TableLayout.FILL表示将剩余的空间填满,如果出现多个TableLayout.FILL,则这几个单元格平分剩余的空间。假设这个容器有500像素宽,则在上面的例子中:
第1列宽度为100,
第2列为(500-100-200)*0.5=100,
第3列为(500-100-200)*0.2=40
第4列为(500-100-200)*0.3/2=30,
第5列为200,
第6列同第3列,为30。
注意:在表示宽或高的像素时范围应该在 0至1之间,而且0.0可以表示成0%或者0个像素,而1只能表示1个像素,不能表示成100%。
创建一个Tablelayout
创建tablelayout就和其他布局管理器一样,直接new一个TableLayout,然后给pannel设置布局panel.setLayout( new TableLayout(size));
为容器添加组件
使用add方法,add(组件,“坐标”),
add(Component comp, Object constraints)参数说明:
Comp: the component to be added
Constraints: an object expressing Layout contraints for this
例如给panel添加button: panel.add(button,“0,0”);如下图:
如果这个button横跨多个单元格,计算顺序是从左上到右下,则字符串的前两个放第一格的坐标,后两个行最后一格的坐标,例如,从(0,0)到(3,0),表示为:panel.add(button,”0,0,3,0”);如下图:
tablelayout 举例详细介绍
下图为实际列子与运行效果图
行和列的分配
此container被分为三行五列。size[0]为列比列分配,width=200是指component的宽度,可以是任意值。写成35/width不直接写成0.15是为了以后的便于修改与直观认识。
参数 p 为TableLayout.PREFERRED:指定行或者列可以根据component自身的大小给予合适的行或列比列,以能全部显示此component。
参数F为TableLayout.FILL:指示行或者列会把container剩下的的空间填满,如上第四列和第五列都为F,则表示第四和第五列会把container剩下的空间填满等分为两份,平均分给第四、第五列。
添加组件
this.add(new JButton("0,0"),"0,0")中constraints为“0,0”两个参数,表示只占0行0列
this.add(new JButton("3,0,3,1"),"3,0,3,1")中constraints为“3,0,3,1”四个参数,表示此component在container中的占用cell为从“3,0”跨度到“3,1”。跨度的方向为左上角到右下角围成的矩形
Tablelayout就说到这里,这里只是说明一下TableLayout的基本的用法,要深入了解TableLayout,可以去官网里面下载。
这里总结一下TableLayout优缺点:
优点: (1)、虽然Tablelayout它不是JDK自带的,但是它是开源的。Tablelaout作为开源的布局框架,可以对核心的类TableLayout.java进行修改达到自己所需要的功能实现。Tablelayout布局与html中表格基本是一样的,我们可以任意而且轻易地合并单元格,可以完成很复杂的布局。 (2)、当窗口的大小发生改变时,在tableLayout布局下得组件也会自动改变,按%比来分配每行,每列的大小。 (3)、TableLayout简单明了,不需要过多设置属性值,也能布局到复杂的外观,而不像GridBagLayout那样需要设置很多的属性(gridx、gridy、insets等等)过于复杂。
缺点:
Tablelaout作为第三方的开源框架,要试用它则必须引入tablelayout的功能jar包,如果只要实现tablelayout简单的功能则只需要引入tablelayout相关的几个类就可以。Tablelayout没有可视化的界面可以设计,不像其它jdk提供的布局在netbeans或者eclipse装入插件后有可视化的编辑界面。