文章目录
Java基础:GUI
GUI(Graphical User Interface):图形用户接口
1、Swing概述
什么是Swing?
- Swing是在原有AWT(抽象窗口工具包)的基础上进行了补充和改进,提供了更加丰富的组件和功能,来满足GUI设计的一切需求。
几点说明:
-
Swing组件的所有类都继承子Container类,然后根据GUI开发的功能扩展了2个主要的分支:容器分支(包括Window窗口和Panel面板)和组件分支。
-
容器分支就是为了实现图形用户界面窗口容器而设计的。
-
组件分支则是为了实现向容器中填充数据、元素以及人机交互组件等功能。
-
Swing组件类中,常用的顶级容器类包括JApplet、JFrame和JDialog。
-
常用组件AbstractButton类及其子类使用来定义按钮常见行为的工具类。
-
JTextComponent类及其子类是用来定义文本内容编辑区区域的工具类。
下面重点介绍 JFrame和 JDialog:
2、Swing顶级容器
2.1、JFrame
- 在Swing组件中,最常见的一个容器就是JFrame;
- JFrame是一个独立存在的顶级容器(也叫窗口),不能放置在其他容器之中;
- JFrame支持通用窗口所有的基本功能,例如窗口最小化、设定窗口大小等;
示例:
import javax.swing.*;
public class JFrameDemo {
public static void main(String[] args) {
// 在主线程中开启另一条线程,比较安全,主线程不能更新 UI
/*SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createWindow();
}
});*/
// lambda表达式
// SwingUtilities.invokeLater(() -> createWindow());
// 方法引用
SwingUtilities.invokeLater(JFrameDemo::createWindow);
}
private static void createWindow() {
JFrame jf = new JFrame();
// 设置窗体可见,不设置无法显示
jf.setVisible(true);
// 设置窗口的标题,也可以写在构造方法中
jf.setTitle("窗口标题");
// 设置关闭窗口时,一同关闭后台的Java程序
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置窗口的大小,单位为像素
jf.setSize(400, 600);
}
}
2.2、JDialog
- JDialog是Swing的另一个顶级容器,通常用来表示对话框窗口;
- JDialog对话框可分为两种:模态对话框和非模态对话框;
- 模态对话框:是指用户需要等到处理完对话框后才能继续与其他对话框交互
- 非模态对话框:是指允许用户在处理对话框的同时与其他窗口交互
常用构造方法:
对话框是模态还是非模态,可以在创建JDialog对象时为构造方法传入参数来设置,也可以在创建JDialog对象后,调用 setModal() 方法来设置
-
modal:true为模态对话框,false为非模态对话框(默认)
-
owner:为对话框拥有者(顶级窗口JFrame),具体是指JDialog对话框在哪个JFrame窗口对象里面。
方法声明 | 功能描述 |
---|---|
JDialog(Frame owner) | 用来创建一个非模态无标题的对话框 |
JDialog(Frame owner, boolean modal) | 创建一个非模态有标题对话框 |
JDialog(Frame owner, boolean modal) | 创建一个指定模式无标题的对话框 |
JDialog(Frame owner, String title, boolean modal) | 创建一个指定模式有标题对话框 |
示例:
import javax.swing.*;
public class JDialogDemo {
public static void main(String[] args) {
SwingUtilities.invokeLater(JDialogDemo::createAndShowGUI);
}
private static void createAndShowGUI() {
// 创建JFrame窗口对象
JFrame jf = new JFrame("窗口标题");
// 设置窗口的宽和高,单位为像素
jf.setSize(400, 600);
// 点击关闭窗口时,关闭后台Java程序
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置窗口可见
jf.setVisible(true);
// 创建JDialog对话框对象,默认为非模态对话框
// JDialog dialog = new JDialog(jf, "对话框标题");
// 模态对话框
JDialog dialog = new JDialog(jf, "对话框标题", true);
// 设置对话框的宽和高,单位为像素
dialog.setSize(300, 200);
// 点击关闭对话框时隐藏对话框
dialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
// 设置对话框可见
dialog.setVisible(true);
}
}
注意:
- 虽然JFrame和JDialog都可以创建顶级容器窗口,但JDialog创建的窗口右上角没有放大和缩小功能;
- 由于创建JDialog容器对象时,设置的模态参数modal为true,所以在操作时,必须先关闭JDialog对话框后,才可以与JFrame窗口对象进行交互;
3、布局管理器
Swing组件不能单独存在,必须放置于容器当中,而组件在容器中的位置和尺寸是由布局管理器决定的。
8大分类:
类 | 解释 |
---|---|
BorderLayout | 边界布局管理器 |
BoxLayout | 箱式布局管理器 |
CardLayout | 卡片布局管理器 |
FlowLayout | 流式布局管理器 |
GridBagLayout | 网格包布布局管理器 |
GridLayout | 网格布局管理器 |
GroupLayout | 分组布局管理器 |
SpringLayout | 弹性布局管理器 |
3.1、BorderLayout
BorderLayout(边界布局管理器)是一种较为复杂的布局方式,它将容器划分为五个区域,分别是页头(PAGE_START)、页尾(PAGE_END)、行头(LINE_START)、行尾(LINE_END)、中部(LINE_CENTER)。
组件可以被放置在这五个区域中的任意一个位置。
使用:
- 向BorderLayout布局管理器的容器中添加组件时,需要使用 JFrame中的 void add(Component comp, Object constraints) 方法。
- 参数 comp表示要添加的组件,constraints 指定组件添加到布局中的位置
- 传参时,可以使用 BorderLayout 类中提供的五个常量设置组件位置。
PAGE_START、PAGE_END、LINE_START、LINE_END、CENTER
示例:
import javax.swing.*;
import java.awt.*;
public class BorderLayoutDemo {
public static void main(String[] args) {
SwingUtilities.invokeLater(BorderLayoutDemo::createAndShowGUI);
}
private static void createAndShowGUI() {
// 1、首先创建顶级容器
JFrame jf = new JFrame("布局管理器标题");
// 2、指定使用哪种布局管理器 --> 边界布局管理器
jf.setLayout(new BorderLayout());
jf.setSize(400, 600);
jf.setLocation(800, 100);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 3、设置组件(按钮)
JButton btn1 = new JButton("PAGE_START");
JButton btn2 = new JButton("PAGE_END");
JButton btn3 = new JButton("LINE_START");
JButton btn4 = new JButton("CENTER");
JButton btn5 = new JButton("LINE_END");
// 4、添加组件
jf.add(btn1, BorderLayout.PAGE_START);
jf.add(btn2, BorderLayout.PAGE_END);
jf.add(btn3, BorderLayout.LINE_START);
jf.add(btn4, BorderLayout.CENTER);
jf.add(btn5, BorderLayout.LINE_END);
// 5、设置容器可见
jf.setVisible(true);
}
}
注意:
- 使用BorderLayout的好处是可以限定各区域的边界,当用户改变容器窗口大小时,各组件的相对位置不变;
- 想BorderLayout的布局管理器添加组件时,如果不指定添加到哪个区域,则默认添加到CENTER区域;
- 每个区域只能放置一个组件,如果向一个区域中添加多个组件时,后放入额组件会覆盖先放入的组件;
3.2、FlowLayout
- FlowLayout(流式布局管理器)是最简单布局管理器
- 在这种布局下,容器会将组件按照添加顺序从左往右放置,当达到容器的边界时,会自动将组件放到下一行的开始位置;
- 这个组件可以按左对齐、居中对齐(默认方式)、右对齐的方式排列
示例:
import javax.swing.*;
import java.awt.*;
public class FlowLayoutDemo {
public static void main(String[] args) {
SwingUtilities.invokeLater(FlowLayoutDemo::creatAndShowGUI);
}
private static void creatAndShowGUI() {
JFrame jf = new JFrame("FlowLayout布局方式");
// jf.setLocation(800, 100);
// jf.setSize(400, 700);
// 同时指定摆放的水平、垂直位置,窗口的宽和高
jf.setBounds(800, 100, 400, 700);
/*
指定布局管理器, 构造方法长度对齐方式、组件之间的水平间距和垂直间距
*/
jf.setLayout(new FlowLayout(FlowLayout.CENTER, 20, 30));
// 添加组件
jf.add(new JButton("按钮1"));
jf.add(new JButton("按钮2"));
jf.add(new JButton("按钮3"));
jf.add(new JButton("按钮4"));
jf.add(new JButton("按钮5"));
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
}
3.3、GridLayout
- GridLayout(网格布局管理器)使用纵横线将容器分成n行m列大小相等的网格,每个网格中可以添加一个组件;
- 添加到容器中的组件会从左往右、从上往下依次填充到网格中;
- 与FlowLayout不同的是:放置在GridLayout布局管理器中的组件将自动占据网格的整个区域;
特点:
- 组件的相对位置不随区域的缩放而改变,但组件的大小会随之改变,组件始终占据网格的整个区域;
缺点:
- 总是忽略组件的最佳大小,所有组件的宽和高都相同
示例:
import javax.swing.*;
import java.awt.*;
public class GridLayoutDemo {
public static void main(String[] args) {
SwingUtilities.invokeLater(GridLayoutDemo::creatAndShowGUI);
}
private static void creatAndShowGUI() {
JFrame jf = new JFrame("GridLayout布局方式");
// jf.setLocation(800, 100);
// jf.setSize(400, 700);
// 同时指定摆放的水平、垂直位置,窗口的宽和高
jf.setBounds(800, 100, 400, 700);
/*
指定布局管理器, 构造方法中指定列数和行数,此外还有组件之间的水平和垂直间距
*/
jf.setLayout(new GridLayout(3, 3));
// 添加组件
for (int i = 1; i <= 9; i++) {
JButton btn = new JButton("按钮" + i);
jf.add(btn);
}
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
}
4、事件处理
4.1、事件处理机制
Swing组件中的时间处理专门用于响应用户的操作,例如,响应用户单击鼠标,按下键盘等操作。
Swing事件处理涉及的三类对象:
名称 | 含义 |
---|---|
事件源(Event Source) | 事件发生的场所,通常就是产生事件的组件,例如窗口、按钮、菜单等 |
事件对象(Event) | 封装了GUI组件上发生的特定事件(通常就是用户的一次操作) |
监听器(Listener) | 负责监听时间源上发生的事件,并对各种事件作出相应处理的对象(对象中包含事件处理器) |
事件处理机制 —— 事件处理流程
事件源是一个组件,当用户进行一些操作时,如按下鼠标或者释放键盘等,都会触发相应的事件,如果事件源注册了监听器,则触发的相应事件将会被处理。
事件处理机制 —— 主要步骤
1、创建事件源
除了一些常见的按钮、键盘等组件可以作为事件源外,包括JFrame窗口在内的顶级容器也可以作为事件源;
2、自定义事件监听器
根据要监听的事件源创建指定类型的监听器进行事件处理,该监听器是一个特殊的Java类,必须时间 XxxListener接口(根据组件触发的动作区分,如WindowsListener用于监听窗口时间,ActionListener用于监听动作事件)
3、为事件源注册监听器
使用addXxxListener()方法为指定事件源添加特定类型的监听器。当事件源上发生监听的事件后,就会触发绑定的事件监听器,然后由监听器中的方法进行相应处理。
示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
public class DemoActionListener {
public static void main(String[] args) {
SwingUtilities.invokeLater(DemoActionListener::createAndShowGUI);
}
private static void createAndShowGUI() {
JFrame jf = new JFrame("事件学习");
jf.setBounds(800, 100, 400, 600);
jf.setLayout(new FlowLayout());
JButton btn = new JButton("按钮");
btn.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("我被点击了");
}
});
jf.add(btn);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
}
4.2、Swing常用事件处理
主要事件分类:
- 窗体事件(WindowEvent)
- 鼠标事件(MouseEvent)
- 键盘事件(KeyEvent)
- 动作事件(ActionEvent)
1、窗体事件(WindowEvent)
对窗体进行操作时,例如窗体的打开、关闭、激活、停用等,这些动作都属于窗体事件。
Java中提供了一个WindowEvent类用于表示窗体事件
使用:
- 首先需要定义一个实现了WindowEvent接口的类作为窗体监听器
- 然后通过 addWindowListener() 方法将窗体对象与窗体监听器进行绑定
示例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
public class WindowListenerDemo {
public static void main(String[] args) {
SwingUtilities.invokeLater(WindowListenerDemo::createAndShowGUI);
}
private static void createAndShowGUI() {
JFrame jf = new JFrame("窗体事件学习");
jf.setBounds(800, 100, 400, 600);
jf.addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
System.out.