十八、Swing程序设计(二)
1. 常用布局管理器
- 在Swing中,每个组件在容器中都有一个具体的位置和大小,而在容器中摆放各种组件时很难判断其具体位置和大小。布局管理器提供了Swing组件安排、展示在容器中的方法以及基本的布局功能。使用布局管理器较程序员直接在容器中控制Swing组件的位置和大小方便得多,可以有效地处理整个窗体的布局。Swing提供的常用布局管理器包括流布局管理器、边界布局管理器以及网格布局管理器。
绝对布局
- 在Swing中,除了使用布局管理器之外还可以使用绝对布局。绝对布局,就是硬性指定组件在容器中的位置和大小,可以使用绝对坐标的方式来指定组件的位置。使用绝对布局的步骤如下:
- 使用Container.setLayout(null)方法取消布局管理器
- 使用Component.setBounds()方法设置每个组件的大小和位置。
import java.awt.*;
import javax.swing.*;
public class AbsolutePosition extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
public AbsolutePosition() {
setTitle("本窗体使用绝对布局"); // 设置该窗体的标题
setLayout(null); // 使该窗体取消布局管理器设置
setBounds(0, 0, 200, 150); // 绝对定位窗体的位置与大小
Container c = getContentPane(); // 创建容器对象
JButton b1 = new JButton("按钮1"); // 创建按钮
JButton b2 = new JButton("按钮2"); // 创建按钮
b1.setBounds(10, 30, 80, 30); // 设置按钮的位置与大小
b2.setBounds(60, 70, 100, 20);
c.add(b1); // 将按钮添加到容器中
c.add(b2);
setVisible(true); // 使窗体可见
// 设置窗体关闭方式
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new AbsolutePosition();
}
}
运行结果:
- 需要注意的是,在使用绝对布局之前需要调用setLayout(null)方法告知编译器,这里不再使用布局管理器。
流布局管理器
- 流布局管理器是最基本的布局管理器,在整个容器中的布局正如其名,像“流”一样从左到右摆放组件,直到占据了这一行的所有空间,然后再向下移动一行。默认情况下,组件在每一行都是居中排列的,但是通过设置也可以更改组件在每一行上的排列位置。
- FlowLayout类中具有以下常用的构造方法:
public FlowLayout()
public FlowLayout(int alignment)
public FlowLayout(int alignment,int horizGap,int vertGap)
- 构造方法中alignment参数表示使用流布局管理器后组件在每一行的具体摆放位置。它可以被赋予以下3个值之一:
FlowLayout.LEFT=0;
FlowLayout.CENTER=1;
FlowLayout.RIGHT=2;
- 上述3个值分别代表容器使用流布局管理器后组件在每一行中的摆放位置。例如将alignment设置为0时,每一行的组件将被指定按照左对齐排列;而将alignment设置为2时,每一行的组件将被指定为按照右对齐排列。
import java.awt.*;
import javax.swing.*;
public class FlowLayoutPosition extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
public FlowLayoutPosition() {
setTitle("本窗体使用流布局管理器"); // 设置窗体标题
Container c = getContentPane();
// 设置窗体使用流布局管理器,使组件右对齐,并且设置组件之间的水平间隔与垂直间隔
setLayout(new FlowLayout(2, 10, 10));
for (int i = 0; i < 10; i++) { // 在容器中循环添加10个按钮
c.add(new JButton("button" + i));
}
setSize(300, 200); // 设置窗体大小
setVisible(true); // 设置窗体可见
// 设置窗体关闭方式
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
public static void main(String[] args) {
new FlowLayoutPosition();
}
}
运行结果:
- 可以看到alignment的值设置为2,故组件右对齐排列,若将alignment的值改为1,则组件会居中对齐。
运行结果:
边界布局管理器
- 在默认不指定窗体布局的情况下,Swing组件的布局模式是边界布局管理器。边界布局管理器将容器划分为东、南、西、北、中5个区域,可以将组件加入到这五个区域中。容器调用Container类的add()方法添加组件时可以设置此组件在边界布局管理器中的区域,区域的控制可以由BorderLayout类中的成员变量来决定,这些成员变量的具体含义如下表:
成员变量 |
含义 |
BorderLayout.NORTH |
在容器中添加组件时,组件置于顶端 |
BorderLayout.SOUTH |
在容器中添加组件时,组件置于底端 |
BorderLayout.EAST |
在容器中添加组件时,组件置于右端 |
BorderLayout.WEST |
在容器中添加组件时,组件置于左端 |
BorderLayout.CENTER |
在容器中添加组件时,组件置于中间开始填充,直到与其他组件边界连接 |
import java.awt.*;
import javax.swing.*;
public class BorderLayoutPosition extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
// 定义组件摆放位置的数组
String[] border = { BorderLayout.CENTER, BorderLayout.NORTH,
BorderLayout.SOUTH, BorderLayout.WEST, BorderLayout.EAST };
String[] buttonName = { "center button", "north button",
"south button", "west button", "east button" };
public BorderLayoutPosition() {
setTitle("这个窗体使用边界布局管理器");
Container c = getContentPane(); // 定义一个容器
setLayout(new BorderLayout()); // 设置容器为边界布局管理器
for (int i = 0; i < border.length; i++) {
// 在容器中添加按钮,并设置按钮布局
c.add(border[i], new JButton(buttonName[i]));
}
setSize(350, 200); // 设置窗体大小
setVisible(true); // 使窗体可视
// 设置窗体关闭方式
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
public static void main(String[] args) {
new BorderLayoutPosition();
}
}
运行结果:
网格布局管理器
- 网格布局管理器将容器划分为网格,所以组件可以按行和按列进行排列。在网格布局管理器中,每一个组件的大小都相同,并且网格中空格的个数由网格的行数和列数决定,如一个两行两列的网格能产生4个大小相同的网格。组件从网格的左上角开始,按照从左到右,从上到下的顺序加入到网格中,而且每一个组件会填满整个网格,改变窗体的大小,组件的大小也会随之改变。
- 网格布局管理器主要有以下两个常用的构造方法:
public GridLayout(int rows,int columns);
public GridLayout(int rows,int columns,int horizGap,int vertGap);
- 在上述构造方法中,rows和columns参数代表网格的行数与列数,这两个参数只有一个参数可以为0,代表一行或一列可以排列任意多个组件;参数horizGap与vertGap指定网格之间的距离,其中horizGap参数指定网格之间的水平距离,vertGap参数指定网格之间的垂直距离。
package com.lzw;
import java.awt.*;
import javax.swing.*;
public class GridLayoutPosition extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
public GridLayoutPosition() {
Container c = getContentPane();
// 设置容器使用网格布局管理器,设置7行3列的网格
setLayout(new GridLayout(7, 3, 5, 5));
for (int i = 0; i < 20; i++) {
c.add(new JButton("button" + i)); // 循环添加按钮
}
setSize(300, 300);
setTitle("这是一个使用网格布局管理器的窗体");
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new GridLayoutPosition();
}
}
运行结果:
- 可以看到组价在窗体中呈现出一个7行3列的网格,并且添加到该布局中的组件被放置在网格中。
网格组布局管理器综合案例:
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);
//
}
}
运行结果:
2. 常用面板
- 面板也是一个Swing容器,它可以作为容器容纳其他组件,但它也必须被添加到其他容器中。Swing中常用的面板包括JPanel面板和JScrollPane面板。
JPanel面板
package com.lzw;
import java.awt.*;
import javax.swing.*;
public class JPanelTest extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
public JPanelTest() {
Container c = getContentPane();
// 将整个容器设置为2行1列的网格布局
c.setLayout(new GridLayout(2, 1, 10, 10));
// 初始化一个面板,设置1行3列的网格布局
JPanel p1 = new JPanel(new GridLayout(1, 3, 10, 10));
JPanel p2 = new JPanel(new GridLayout(1, 2, 10, 10));
JPanel p3 = new JPanel(new GridLayout(1, 2, 10, 10));
JPanel p4 = new JPanel(new GridLayout(2, 1, 10, 10));
p1.add(new JButton("1")); // 在面板中添加按钮
p1.add(new JButton("1"));
p1.add(new JButton("2"));
p1.add(new JButton("3"));
p2.add(new JButton("4"));
p2.add(new JButton("5"));
p3.add(new JButton("6"));
p3.add(new JButton("7"));
p4.add(new JButton("8"));
p4.add(new JButton("9"));
c.add(p1); // 在容器中添加面板
c.add(p2);
c.add(p3);
c.add(p4);
setTitle("在这个窗体中使用了面板");
setSize(420, 200);
setVisible(true);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
public static void main(String[] args) {
new JPanelTest();
}
}
运行结果:
- 在这个实例中,首先设置整个窗体的布局为2行1列的网格布局,然后先后定义4个面板,分别为4个面板设置网格布局,行列数会有所不同,将按钮放置在每个面板中,最后将面板添加至容器中。
JScrollPane面板
- 在设置界面时,可能会遇到在一个较小的容器窗体中显示一个较大部分的内容的情况,这时可以使用JScrollPane面板。JScrollPane面板是带滚动条的面板,它也是一种容器,但是JScrollPane只能放置一个组件,并且不可以使用布局管理器。如果需要在JScrollPane面板放置多个组件,需要将多个组件放在JPanel面板上,然后将JPanel面板作为一个整体组件添加在JScrollPane组件上。
package com.lzw;
import java.awt.*;
import javax.swing.*;
public class JScrollPaneTest extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
public JScrollPaneTest() {
Container c = getContentPane(); // 创建容器
JTextArea ta = new JTextArea(20, 50); // 创建文本区域组件
JScrollPane sp = new JScrollPane(ta); // 创建JScrollPane面板对象
c.add(sp); // 将该面板添加到该容器中
setTitle("带滚动条的文字编译器");
setSize(200, 200);
setVisible(true);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
public static void main(String[] args) {
new JScrollPaneTest();
}
}
运行结果: