文章目录
零、本讲学习目标
1、熟悉JFrame和JDialog顶级容器的基本使用
2、掌握Swing的常用布局管理器的使用
一、Swing概述
要不要学习Swing或者AWT这个问题,完全取决于个人的发展方向。严格说来,如果你以后想要从事Web方向的开发,确实可以不用学习,但是如果以后想要从事GUI编程或者C/S编程的工作,那么肯定是要学习Swing相关知识的。
软件开发中,语言都是相通的,没有哪个语言优于哪个语言的说法。俗话说,书到用时方恨少,知识也是一样,患寡不患多。从整个Java体系来看,要想全面地熟悉Java语言,还是需要学会GUI编程的,毕竟这也是Java大体系里面不可缺少的一环。熟悉GUI编程对于以后的开发也大有裨益。
(一)AWT是何物?
1、AWT定义
在早期JDK1.0发布时,Sun公司就为GUI开发提供了一套基础类库,这套类库被称为AWT(Abstract Window Toolkit
),即抽象窗口工具包。AWT起初设想就是为了统一实现不同操作系统的图像界面。
2、AWT缺陷
- 不同操作系统图形库的功能可能不一样,在一个平台上存在的功能在另外一个平台上则可能不存在,为此AWT不得不通过牺牲功能来实现平台无关性。
- AWT是一个重量级组件,使用麻烦,设计出的图形界面不够美观且功能有限。
(二)Swing是何物?
1、Swing定义
Swing是在原有的AWT的基础上进行了补充和改进,提供了更加丰富的组件和功能,来满足GUI设计的一切需求。
2、Swing与AWT的关系
- Swing是一种轻量级组件,它由Java语言开发,同时底层以AWT为基础。
- 同AWT相比,在实际开发中,更多的是使用Swing进行图形用户界面开发。
- Swing组件为实现图形用户界面提供了很多基础类库,多数位于java.awt、javax.swing包及其子包下。
3、Swing组件继承关系图
- Swing组件的所有类都继承自Container类,然后根据GUI开发的功能扩展了2个主要分支:容器分支(包括Window窗口和Panel面板)和组件分支。
- 容器分支就是为了实现图形用户界面窗口容器而设计的。
- 组件分支则是为了实现向容器中填充数据、元素以及人机交互组件等功能。
- Swing组件类中,常用的顶级容器类包括有JApplet、JFrame和JDialog。
- 常用组件AbstractButton类及其子类是用来定义按钮常见行为的工具类。
- JTextComponent类及其子类就是用来定义文本内容编辑区域的工具类。
二、Swing顶级容器
Swing提供了三个主要的顶级容器类:JFrame、JDialog和JApplet,其中JFrame和JDialog是最为常用也是最为简单的顶级容器,下面我们就一起来学习如何使用这两种顶级容器。
(一)JFrame - 窗口
1、JFrame概述
- 在Swing组件中,最常见的一个容器就是JFrame。
- JFrame是一个独立存在的顶级容器(也叫窗口),不能放置在其他容器之中。
- JFrame支持通用窗口所有的基本功能,例如窗口最小化、设定窗口大小等。
2、JFrame继承关系图
3、JFrame常用构造方法
方法声明 | 功能描述 |
---|---|
JFrame() | 创建一个窗体对象,不指定标题 |
JFrame(String title) | 创建一个窗体对象,并指定标题 |
在实际开发中,我们用得最多的是第二个构造方法,参数用于指定窗口的标题:
4、案例演示:创建登录窗口
现在我们只能创建一个空的登录窗口,等我们学习了布局管理器与常用的组件(标签、文本框与按钮),我们就可以改进这个程序,做出一个可以输入用户名与密码的登录窗口。
- 继承JFrame类,创建登录窗口类LoginFrame
- 编写应用程序框架
package net.hw.lesson29;
import javax.swing.*;
import java.awt.*;
/**
* 功能:创建登录窗口
* 作者:华卫
* 日期:2020年05月30日
*/
public class LoginFrame extends JFrame {
/**
* 构造方法
*
* @param title
* @throws HeadlessException
*/
public LoginFrame(String title) throws HeadlessException {
super(title); // 调用父类构造方法传入标题参数
initGUI(); // 调用初始化图形用户界面方法
}
/**
* 初始化图形用户界面方法
*/
private void initGUI() {
}
/**
* 主方法
*
* @param args
*/
public static void main(String[] args) {
// 实例化登录窗口对象
LoginFrame loginFrame = new LoginFrame("登录窗口");
}
}
- 编写initGUI()方法
private void initGUI() {
// 设置窗口边界
setBounds(200, 200, 300, 200);
// 设置窗口可见
setVisible(true);
}
-
运行程序,查看结果
-
简要说明
– 如果不设置窗口初始位置,那么只需要调用setSize()方法,设置窗口的宽度与高度
– 窗口出现后,单击关闭按钮,窗口消失不见了,但是应用程序或进程还未结束,必须单击工具栏上那个红色的停止按钮,强行终止应用程序,可以看到进程结束的退出码是-1。 -
修改代码,让窗口启动时屏幕居中显示,单击关闭按钮就退出应用程序
private void initGUI() {
// 设置窗口边界
setBounds(200, 200, 300, 200);
// 设置屏幕居中(采用相对定位方式)
setLocationRelativeTo(null);
// 设置窗口可见
setVisible(true);
// 设置默认关闭方式(关闭窗口就退出应用程序)
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
- 运行程序,查看效果
5、课堂练习:创建并显示一个窗口
- 创建Exercise2901
- 在主方法里创建窗口对象,设置窗口标题“学生信息”
- 设置窗口尺寸,宽度400,高度300
- 设置窗口启动时屏幕居中
- 设置窗口的可见属性,将窗口显示在屏幕上
- 设置窗口关闭方式,关闭窗口即退出应用程序
(二)JDialog - 对话框
1、JDialog概述
Dialog是Swing的另外一个顶级容器,通常用来表示对话框窗口。
JDialog对话框可分为两种:模态对话框和非模态对话框。
- 模态对话框是指用户需要等到处理完对话框后才能继续与其他窗口交互。
- 非模态对话框是指允许用户在处理对话框的同时还可以与其他窗口交互。
对话框是模态或者非模态,可以在创建JDialog对象时为构造方法传入参数来设置,也可以在创建JDialog对象后调用它的setModal()方法来进行设置。
2、JDialog继承关系图
3、JDialog常用构造方法
方法声明 | 功能描述 |
---|---|
JDialog(Frame owner) | 构造方法,用来创建一个非模态的对话框,owner为对话框所有者(顶级窗口JFrame) |
JDialog(Frame owner,String title) | 构造方法,创建一个具有指定标题的非模态对话框 |
JDialog(Frame owner,boolean modal) | 创建一个有指定模式的无标题对话框,默认值false(即非模态对话框) |
4、案例演示:显示窗口与对话框
- 创建Example2901
package net.hw.lesson29;
import javax.swing.*;
/**
* 功能:显示窗口与对话框
* 作者:华卫
* 日期:2020年05月30日
*/
public class Example2901 {
/**
* 初始化图形用户界面
*/
public static void initGUI() {
// 创建窗口对象
JFrame frame = new JFrame("JFrame窗口");
// 设置窗口边界
frame.setBounds(200, 200, 300, 200);
// 设置屏幕居中(采用相对定位方式)
frame.setLocationRelativeTo(null);
// 设置窗口可见
frame.setVisible(true);
// 设置默认关闭方式(关闭窗口就退出应用程序)
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 基于窗口创建对话框对象
JDialog dialog = new JDialog(frame, "JDialog对话框", true);
// 设置默认关闭方式(关闭对话框就隐藏对话框)
dialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
// 设置对话框大小
dialog.setSize(200, 100);
// 设置对话框在窗口居中
dialog.setLocationRelativeTo(frame);
// 设置对话框可见
dialog.setVisible(true);
}
public static void main(String[] args) {
// 使用SwingUtils工具类调用initGUI()方法
SwingUtilities.invokeLater(Example2901::initGUI);
}
}
- 运行程序,查看结果
- 简单说明
– 虽然JFrame和JDialog都可以创建顶级容器窗口,但JDialog创建的窗口右上角没有放大和缩小功能。
– 由于创建JDialog容器对象时,设置的模态参数modal为true,所以在操作时,必须先关闭JDialog对话框后才可以与JFrame窗口进行交互。
三、布局管理器
(一)布局管理器概述
Swing组件不能单独存在,必须放置于容器当中,而组件在容器中的位置和尺寸是由布局管理器来决定的。
(二)布局管理器分类
(三)边界布局管理器(BorderLayout)
1、边界布局管理器概述
BorderLayout(边界布局管理器)是一种较为复杂的布局方式,它将容器划分为五个区域,分别是页头(PAGE_START
)、页尾(PAGE_END
)、行首(LINE_START
)、行尾(LINE_END
)、中部(CENTER
)。组件可以被放置在这五个区域中的任意一个位置。
2、边界布局管理器使用方法
- 向BorderLayout布局管理器的容器中添加组件时,需要使用add(Component comp, Object constraints)方法。
- 参数comp表示要添加的组件,constraints指定将组件添加到布局中的位置,它是一个Object类型。
- 传参时可以使用BorderLayout类提供的5个常量设置组件位置,它们分别是
PAGE_START
、PAGE_END
、LINE_START
、LINE_END
和CENTER
。 - BorderLayout的好处就是可以限定各区域的边界,当用户改变容器窗口大小时,各个组件的相对位置不变。
- 向BorderLayout的布局管理器添加组件时,如果不指定添加到哪个区域,则默认添加到CENTER区域。
- 每个区域只能放置一个组件,如果向一个区域中添加多个组件时,后放入的组件会覆盖先放入的组件。
3、案例演示:演示边界布局效果
- 继承JFrame,创建BorderLayoutDemo
package net.hw.lesson29;
import javax.swing.*;
import java.awt.*;
/**
* 功能:演示边界布局效果
* 作者:华卫
* 日期:2020年05月30日
*/
public class BorderLayoutDemo extends JFrame {
public BorderLayoutDemo(String title) throws HeadlessException {
super(title); // 调用父类构造方法传入标题参数
initGUI(); // 调用初始化图形用户界面方法
}
/**
* 初始化图形用户界面方法
*/
private void initGUI() {
// 设置边界布局管理器
setLayout(new BorderLayout());
// 设置窗口边界
setBounds(200, 200, 400, 300);
// 设置屏幕居中(采用相对定位方式)
setLocationRelativeTo(null);
// 创建五个按钮
JButton btnNorth = new JButton("北方");
JButton btnSouth = new JButton("南方");
JButton btnWest = new JButton("西方");
JButton btnCenter = new JButton("中原");
JButton btnEast = new JButton("东方");
// 添加按钮到窗口指定区域
add(btnNorth, BorderLayout.PAGE_START); // BorderLayout.NORTH
add(btnSouth, BorderLayout.PAGE_END); // BorderLayout.SOUTH
add(btnWest, BorderLayout.LINE_START); // BorderLayout.WEST
add(btnCenter, BorderLayout.CENTER);
add(btnEast, BorderLayout.LINE_END); // BorderLayout.EAST
// 设置窗口可见
setVisible(true);
// 设置默认关闭方式(关闭窗口就退出应用程序)
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new BorderLayoutDemo("演示边界布局");
}
}
- 运行程序,查看结果
4、温馨小贴士
在使用BorderLayout边界布局管理器过程中,当使用add(Component comp,Object constraints)方法向容器区域中添加指定组件和位置时,除了可以使用前面介绍的PAGE_START、PAGE_END、LINE_START、LINE_END和CENTER常量参数指定组件位置,也可以使用NORTH、SOUTH、EAST、WEST和CENTER常量参数来指定组件位置,只不过案例BorderLayoutDemo里使用的常量参数是JDK 1.4版本开始出现的,适合不同语言标准,也是官方相对推荐的。
(四)流式布局管理器(FlowLayout)
1、流式布局管理器概述
- FlowLayout(流式布局管理器)是最简单的布局管理器。
- 在这种布局下,容器会将组件按照添加顺序从左向右放置,当到达容器的边界时,会自动将组件放到下一行的开始位置。
- 这些组件可以按左对齐、居中对齐(默认方式)或右对齐的方式排列。
2、流式布局管理器构造方法
方法声明 | 功能描述 |
---|---|
FlowLayout() | 组件默认居中对齐,水平、垂直间距默认为5个单位 |
FlowLayout(int align) | 指定组件相对于容器的对齐方式,水平、垂直间距默认为5个单位 |
FlowLayout(int align, int hgap, int vgap) | 指定组件的对齐方式和水平、垂直间距 |
- 参数align决定组件在每行中相对于容器边界的对齐方式,分别为左对齐、右对齐、居中对齐。
- 对齐方式可以使用该类中提供的常量
FlowLayout.LEFT
、FlowLayout.RIGHT
、FlowLayout.CENTER
表示。 - 参数hgap和参数vgap分别设定组件之间的水平和垂直间距,可以填入一个任意数值。
3、案例演示:演示流式布局效果
- 继承JFrame,创建FlowLayoutDemo
package net.hw.lesson29;
import javax.swing.*;
import java.awt.*;
/**
* 功能:演示流式布局效果
* 作者:华卫
* 日期:2020年05月30日
*/
public class FlowLayoutDemo extends JFrame {
public FlowLayoutDemo(String title) throws HeadlessException {
super(title); // 调用父类构造方法传入标题参数
initGUI(); // 调用初始化图形用户界面方法
}
/**
* 初始化图形用户界面方法
*/
private void initGUI() {
// 设置流式布局管理器
setLayout(new FlowLayout(FlowLayout.LEFT, 20, 30));
// 设置窗口边界
setBounds(200, 200, 400, 300);
// 设置屏幕居中(采用相对定位方式)
setLocationRelativeTo(null);
// 创建五个按钮
JButton button1 = new JButton("第一个按钮");
JButton button2 = new JButton("第二个按钮");
JButton button3 = new JButton("第三个按钮");
JButton button4 = new JButton("第四个按钮");
JButton button5 = new JButton("第五个按钮");
// 添加按钮到窗口
add(button1);
add(button2);
add(button3);
add(button4);
add(button5);
// 设置窗口可见
setVisible(true);
// 设置默认关闭方式(关闭窗口就退出应用程序)
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new FlowLayoutDemo("演示流式布局");
}
}
- 运行程序,查看结果
(五)网格布局管理器(GridLayout)
1、网格布局管理器概述
- GridLayout(网格布局管理器)使用纵横线将容器分成n行m列大小相等的网格,每个网格中可以添加一个组件。
- 添加到容器中的组件会从左向右、从上向下依次填充到网格中。
- 与FlowLayout不同的是,放置在GridLayout布局管理器中的组件将自动占据网格的整个区域
2、网格布局管理器构造方法
方法声明 | 功能描述 |
---|---|
GridLayout() | 默认只有一行,每个组件占一列 |
GridLayout(int rows, int cols) | 指定容器的行数和列数 |
GridLayout(int rows, int cols, int hgap, int vgap) | 指定容器的行数和列数以及组件之间的水平、垂直间距 |
- 说明:参数rows代表行数,cols代表列数,hgap和vgap规定窗格之间水平和垂直方向的间距。
3、网格布局特点
对于网格布局,组件的相对位置不随区域的缩放而改变,但组件的大小会随之改变,组件始终占据网格的整个区域。存在一个缺点:总是忽略组件的最佳大小,所有组件的宽高都相同。
4、案例演示:演示网格布局效果
- 继承JFrame,创建GridLayoutDemo
package net.hw.lesson29;
import javax.swing.*;
import java.awt.*;
/**
* 功能:演示网格布局效果
* 作者:华卫
* 日期:2020年05月30日
*/
public class GridLayoutDemo extends JFrame {
public GridLayoutDemo(String title) throws HeadlessException {
super(title); // 调用父类构造方法传入标题参数
initGUI(); // 调用初始化图形用户界面方法
}
/**
* 初始化图形用户界面方法
*/
private void initGUI() {
// 设置网格布局管理器
setLayout(new GridLayout(3, 3, 10, 5));
// 设置窗口边界
setBounds(200, 200, 400, 300);
// 设置屏幕居中(采用相对定位方式)
setLocationRelativeTo(null);
// 创建五个按钮
JButton button1 = new JButton("第一个按钮");
JButton button2 = new JButton("第二个按钮");
JButton button3 = new JButton("第三个按钮");
JButton button4 = new JButton("第四个按钮");
JButton button5 = new JButton("第五个按钮");
JButton button6 = new JButton("第六个按钮");
JButton button7 = new JButton("第七个按钮");
JButton button8 = new JButton("第八个按钮");
// 添加按钮到窗口
add(button1);
add(button2);
add(button3);
add(button4);
add(button5);
add(button6);
add(button7);
add(button8);
// 设置窗口可见
setVisible(true);
// 设置默认关闭方式(关闭窗口就退出应用程序)
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new GridLayoutDemo("演示网格布局");
}
}
- 运行程序,查看结果
四、利用布局管理器与组件改进登录窗口
- 修改LoginFrame的initGUI()方法,设置布局,添加面板与组件
package net.hw.lesson29;
import javax.swing.*;
import java.awt.*;
/**
* 功能:创建登录窗口
* 作者:华卫
* 日期:2020年05月30日
*/
public class LoginFrame extends JFrame {
/**
* 构造方法
*
* @param title
* @throws HeadlessException
*/
public LoginFrame(String title) throws HeadlessException {
super(title); // 调用父类构造方法传入标题参数
initGUI(); // 调用初始化图形用户界面方法
}
/**
* 初始化图形用户界面方法
*/
private void initGUI() {
// 创建三个面板
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
JPanel panel3 = new JPanel();
// 获取内容面板
JPanel panel = (JPanel) getContentPane();
// 设置面板panel的布局为表格布局
panel.setLayout(new GridLayout(3,1));
// 将三个小面板添加到面板panel里
panel.add(panel1);
panel.add(panel2);
panel.add(panel3);
/* 第一个面板里要添加用户名标签与文本框 */
// 创建用户名标签
JLabel lblUsername = new JLabel("用户名:");
// 创建用户名文本框
JTextField txtUsername = new JTextField(15);
// 将标签与文本框添加到第一个面板
panel1.add(lblUsername);
panel1.add(txtUsername);
/* 第二个面板里要添加密码标签与文本框 */
// 创建密码标签
JLabel lblPassword = new JLabel("密 码:");
// 创建密码文本框
JPasswordField txtPassword = new JPasswordField(15);
// 将标签与文本框添加到第二个面板
panel2.add(lblPassword);
panel2.add(txtPassword);
/* 第三个面板里要添加两个按钮 */
// 创建登录按钮
JButton btnLogin = new JButton("登录");
// 创建取消按钮
JButton btnCancel = new JButton("取消");
// 将两个按钮添加到第三个面板
panel3.add(btnLogin);
panel3.add(btnCancel);
// 设置窗口边界
setBounds(200, 200, 300, 200);
// 设置屏幕居中
setLocationRelativeTo(null);
// 设置窗口紧凑
pack();
// 设置窗口可见
setVisible(true);
// 设置默认关闭方式
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
/**
* 主方法
*
* @param args
*/
public static void main(String[] args) {
// 实例化登录窗口对象
LoginFrame loginFrame = new LoginFrame("登录窗口");
JDialog dialog;
}
}
- 运行程序,查看结果
- 可以在用户名与密码文本框里输入数据,并且密码文本框回显的是一串大圆点
- 单击【确定】和【取消】按钮,没有任何反应,因为我们还没有编写事件处理方法
- 下一讲,我们会学习Swing事件处理机制,然后我们再来改进这个登录窗口程序。
五、课后作业:创建修改密码窗口
- 继承JFrame,创建ChangePasswordFrame
- 设置布局,添加组件,设置窗口属性
- 用户名文本框不可用(调用setEnabled()方法,传入false参数)
- 给两个按钮设置热键字母(调用setMnemonic()方法)
btnOK = new JButton("确定[O]");
btnOK.setMnemonic(KeyEvent.VK_O);
btnCancel = new JButton("取消[C]");
btnCancel.setMnemonic(KeyEvent.VK_C);