Swing之布局管理器

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_STARTPAGE_ENDLINE_STARTLINE_END。在ComponentOrientation 设置为ComponentOrientation.LEFT_TO_RIGHT 的容器中,这些常量分别映射到NORTHSOUTHWESTEAST

为了与以前的版本兼容,BorderLayout 还包括相对定位常量 BEFORE_FIRST_LINEAFTER_LAST_LINEBEFORE_LINE_BEGINSAFTER_LINE_ENDS。这些常量分别等同于PAGE_STARTPAGE_ENDLINE_STARTLINE_END。为了与其他组件使用的相对定位常量一致,应优先使用后一组常量。

将绝对定位常量与相对定位常量混合会产生无法预料的结果。如果两种类型的常量都使用,则优先采用相对常量。例如,如果同时使用 NORTHPAGE_START 常量在方向性为LEFT_TO_RIGHT 的容器中添加组件,则只体现PAGE_START 布局。

注:目前,在 Java 2 Platform v1.2 中,BorderLayout 不支持垂直方向。不考虑容器的 ComponentOrientationisVertical 设置。

根据其首选大小和容器大小的约束 (constraints) 对组件进行布局。NORTHSOUTH 组件可以在水平方向上拉伸;而EASTWEST 组件可以在垂直方向上拉伸;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 属性确定。可能的值为:

例如,以下图片显示了使用流布局管理器(它的默认布局管理器)来定位三个按钮的 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 官方文档结束----


使用时需要注意的问题

。。。好累 可怜,改天有兴致再写吧。
。。。未完待续。。。



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java Swing 的盒子布局管理器(Box Layout Manager)是一种非常常用的布局管理器。它可以将组件垂直或水平地排列,使组件之间具有等距离的间隔。盒子布局管理器使用了一个概念叫做盒子(Box),可以是水平盒子(Horizontal Box)或者垂直盒子(Vertical Box)。在盒子中,每个组件都沿着盒子的方向排列,可以根据需要设置组件之间的间距,也可以设置组件的对齐方式。 使用盒子布局管理器的步骤如下: 1. 创建一个容器对象,例如 JPanel。 2. 调用 JPanel 的 setLayout 方法,设置盒子布局管理器。 3. 创建需要添加到容器中的组件对象。 4. 调用容器的 add 方法,将组件添加到容器中。 下面是一个创建水平盒子的示例代码: ``` JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); JLabel label1 = new JLabel("Label 1"); JLabel label2 = new JLabel("Label 2"); JLabel label3 = new JLabel("Label 3"); panel.add(label1); panel.add(Box.createHorizontalStrut(10)); // 添加一个水平间距 panel.add(label2); panel.add(Box.createHorizontalGlue()); // 添加一个水平可伸缩的空白区域 panel.add(label3); ``` 在这个示例中,创建了一个 JPanel 对象,并设置了水平盒子布局管理器。然后创建了三个 JLabel 组件,分别添加到 JPanel 中,并使用了 Box.createHorizontalStrut 和 Box.createHorizontalGlue 方法添加了水平间距和可伸缩的空白区域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值