1 API 概述
1.1 API概述
API(Application Programming Interface) :应用程序编程接口
Java API :指的就是 JDK 中提供的各种功能的 Java类。
为了帮助我们使用这些类,Java还提供了对应的帮助文档。
1.1.1 帮助文档的使用
这个文档对应的是JDK11版本的,是目前比较新的中文版的帮助文档。
文档打开后,找到索引这里,下面有一个输入框,在这个框框里输入我们要学习的API。
在这个框框里面我们输入:String,然后一回车,看到一个新的界面,这个界面中就是关于String相关的知识了
接着,我们来说一下,在学习一个API的时候,我们重点要看 四个地方:
第一个地方:看类所在的包
因为java.lang包下的类,我们是可以直接使用的,不需要导包。其他包下的类,我们都是要导包后才能使用的
第二个地方:看类的描述
比如说:String类表示字符串。 Java程序中的所有字符串文字(例如"abc" )都实现为此类的实例。告诉了我们String就是用来表示字符串的类,直接写一个字符串数据:abc就是String类的一个对象。
第三个地方:看类的构造方法
往下滑,这就是String类的构造方法,为什么要看构造方法呢?因为我们在使用一个类的时候,其实使用的是该类的对象,而创建对象,我们是需要通过构造方法实现的,所以,我们得看看它提供了哪些构造方法。
第四个地方:看类的成员方法
这是我们学习一个API的重点,我们之所以学习一个API,重点就是为了使用该API来完成某些功能。而API的功能,都是通过一个个方法实现的,所以我们重点得看看类的成员方法。
先看描述,通过描述,我们就知道了方法是干什么的。
再看方法名和参数,这样我们就知道调用哪个方法,以及参数的类型和个数。
最后,我们看返回值类型,这样我们就知道调用该方法后,最终给我们返回了一个什么类型结果
总结一下帮助文档的使用流程:
① 打开帮助文档
② 找到索引选项,输入要学习的API,然后回车
③ 看类所在包:因为java.lang包下的类在使用的时候不需要导包
④ 看类的描述:这样我们就知道了类是干什么的
⑤ 看类的构造方法:这样我们就可以创建对象了
⑥ 看类的成员方法:这样我们就可以通过这些方法完成某些功能了
1.2 包和导包
- 那什么是包呢?
- 包其实就是文件夹
- 作用:对类进行分类管理
- 包的定义格式:
- 格式:package 包名;
- 注意:包名一般是公司域名反写,并且多级包用.分开
- 举例:www.itheima.com
- 范例:package com.itheima;
知道了如何定义包之后,下面我们来定义两个包,并且在不同包下定义同名的类。
package com.itheima_01;
public class Student {
public void study(){
System.out.println("好好学习天天向上");
}
}
package com.itheima_01;
public class StudentTest {
public static void main(String[] args) {
Student s = new Student();
s.study();
}
}
package com.itheima_02;
public class StudentTest {
public static void main(String[] args) {
com.itheima_01.Student s1 = new com.itheima_01.Student();
s1.study();
com.itheima_01.Student s2 = new com.itheima_01.Student();
s2.study();
}
}
使用不同包下的类时,使用的时候要写类的全路径,写起来太麻烦了。为了简化带包的操作,Java就提供了导包的功能。
- 导包的格式:
- 格式:import 包名;
- 范例:import com.itheima.Student;
- 导包的三种方式:
- 手动导包
- 快捷键导包:Alt+Enter
- 写一个类,写一部分的时候,如果给出了对应的提示,回车后会自动导包
package com.itheima_02;
import com.itheima_01.Student;
//Alt+Enter 快捷键导包
public class StudentTest {
public static void main(String[] args) {
// com.itheima_01.Student s1 = new com.itheima_01.Student();
// s1.study();
// com.itheima_01.Student s2 = new com.itheima_01.Student();
// s2.study();
Student s1 = new Student();
s1.study();
Student s2 = new Student();
s2.study();
}
}
2 Scanner
2.1 Scanner基本使用
通过查看帮助文档,我们知道了如下的信息:
- Scanner:
- 一个简单的文本扫描程序,可以获取基本类型数据和字符串数据
- 构造方法:
- Scanner(InputStream source):创建 Scanner 对象
- System.in:对应的是InputStream类型,可以表示键盘输入
- Scanner sc = new Scanner(System.in);
- 成员方法:
- int nextInt():获取一个int类型的数据
- int i = sc.nextInt();
/*
Scanner的基本使用
*/
public class ScannerDemo {
public static void main(String[] args) {
//Scanner(InputStream source):创建 Scanner 对象
Scanner sc = new Scanner(System.in);
//int nextInt():获取一个int类型的数据
System.out.println("请输入一个整数:");
int i = sc.nextInt();
//输出获取到的数据
System.out.println("你输入的数据是:" + i);
//简便写法
System.out.println("请输入一个整数");
int ii = new Scanner(System.in).nextInt();
System.out.println("您输入的整数为" + i);
}
}
2.2 练习(数据求和)
需求:键盘录入两个整数,求两个数据和,并在控制台输出求和结果
分析:
① 创建键盘录入数据对象
② 通过键盘录入数据对象调用nextInt()方法获取数据
③ 对获取的两个整数求和
④ 在控制台输出求和结果
/*
需求:键盘录入两个整数,求两个数据和,并在控制台输出求和结果
分析:
1:创建键盘录入数据对象
2:通过键盘录入数据对象调用nextInt()方法获取数据
3:对获取的两个整数求和
4:在控制台输出求和结果
*/
public class ScannerTest {
public static void main(String[] args) {
//创建键盘录入数据对象
Scanner sc = new Scanner(System.in);
//通过键盘录入数据对象调用nextInt()方法获取数据
System.out.println("请输入第一个整数:");
int firstNumber = sc.nextInt();
System.out.println("请输入第二个整数:");
int secondNumber = sc.nextInt();
//对获取的两个整数求和
int sum = firstNumber + secondNumber;
//在控制台输出求和结果
System.out.println("求和结果是:" + sum);
//简便写法
System.out.println("请输入第一个整数:");
int firstNumber1 = new Scanner(System.in).nextInt();
System.out.println("请输入第二个整数:");
int secondNumber1 = new Scanner(System.in).nextInt();
int sum1 = firstNumber1 + secondNumber1;
System.out.println("您输入的两个数字的和是:" + sum1);
}
}
3 Random
3.1 Random基本使用
通过查看帮助文档,我们知道了如下的信息:
- Random:
- 该类的实例用于生成随机数
- 构造方法:
- Random():创建一个新的随机数生成器
- 成员方法:
- int nextInt(int bound):获取一个int类型的随机数,参数bound表示获取到的随机数在[0,bound)之间
/*
Random的基本使用
*/
public class RandomDemo {
public static void main(String[] args) {
//Random():创建一个新的随机数生成器
Random r = new Random();
//int nextInt(int bound):获取一个int类型的随机数,参数bound表示获取到的随机数在[0,bound)之间
// int i = r.nextInt(10);
// System.out.println(i);
// for (int i=1; i<=10; i++) {
// int j = r.nextInt(10);
// System.out.println(j);
// }
//需求:如何获取1-100之间的随机数呢?
// int number = r.nextInt(100);//0-99
// int number = r.nextInt(101);//0-100
int number = r.nextInt(100) + 1;
System.out.println(number);
}
}
3.2 练习(猜数字游戏)
需求:系统自动产生一个1-100之间的整数,使用程序实现猜这个数字是多少?
猜的时候根据不同情况给出相应的提示
如果猜的数字比真实数字大,提示你猜的数据大了
如果猜的数字比真实数字小,提示你猜的数据小了
如果猜的数字与真实数字相等,提示恭喜你猜中了
分析:
① 使用Random获取一个1-100之间的整数
② 使用Scanner实现键盘录入猜的数据值
③ 使用if…else if…else 的格式实现猜数字,并给出对应的提示
import java.util.Random;
import java.util.Scanner;
/*
需求:系统自动产生一个1-100之间的整数,使用程序实现猜这个数字是多少?
猜的时候根据不同情况给出相应的提示
如果猜的数字比真实数字大,提示你猜的数据大了
如果猜的数字比真实数字小,提示你猜的数据小了
如果猜的数字与真实数字相等,提示恭喜你猜中了
分析:
1:使用Random获取一个1-100之间的整数
2:使用Scanner实现键盘录入猜的数据值
3:使用if…else if…else 的格式实现猜数字,并给出对应的提示
*/
public class RandomTest {
public static void main(String[] args) {
//使用Random获取一个1-100之间的整数
Random r = new Random();
int number = r.nextInt(100) + 1;
System.out.println("系统已经产生了一个1-100之间的整数");
while (true) {
//使用Scanner实现键盘录入猜的数据值
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要猜的数字:");
int guessNumber = sc.nextInt();
//使用if…else if…else 的格式实现猜数字,并给出对应的提示
if (guessNumber > number) {
System.out.println("你猜的数据" + guessNumber + "大了");
} else if (guessNumber < number) {
System.out.println("你猜的数据" + guessNumber + "小了");
} else {
System.out.println("恭喜你猜中了");
break;
}
}
}
}
4 GUI
4.1 GUI概述
- GUI:Graphical User Interface(图形用户接口)
- 用图形的方式,来显示计算机操作的界面
Java为GUI提供的API都存在java.awt和javax.Swing两个包中,我们分别来看一下这两个包:
- java.awt 包:
- awt是这三个单词首字母的缩写,翻译过来是抽象窗口工具包,只不过这个包的API,需要调用本地系统方法实现功能,和本地系统有关联,不利于代码移植,属重量级控件
- javax.swing 包:
- 它是在awt的基础上,建立的一套图形界面系统,提供了更多的组件,而且完全由Java实现。增强了移植性,属轻量级控件
所以,我们做图形界面开发使用的是swing包下的类。
- 组件是具有图形表示的对象,该图形表示可以显示在屏幕上并且可以与用户交互
比如说,在用户登录中,文本框和按钮等,都是能够表示图形的对象,所以它们都称为组件。
常用组件:
- 组件:
- 基本组件:具有图形表示的对象
- 容器组件:是可以添加组件的组件。也就是在容器中可以通过add方法添加组件,既可以添加基本组件,也可以添加容器组件。
- 我们先来看常用的基本组件:
- JButton,这是按钮
- JLabel,这是用来显示文本内容的,或者展示图片使用
- JTextFile,这是文本框,用来输入内容的
- JTextArea,这是文本域,用来输入多行多列的数据的
- 接着,我们再来看容器组件:
- 面板也是一个容器,我们常用JPanel,后面用到在具体讲解
- 窗体,下面是Frame,这是awt包下,而我们使用的是JFrame,这是swing包下。
由于我们使用的都是swing包下的,所以将来使用的组件,都是以J开头的。
4.2 常用组件
4.2.1 JFrame(初识窗体)
- JFrame:
- 是一个顶层窗口
- 构造方法:
- JFrame():构造一个最初不可见的新窗体
- 成员方法:
- void setVisible(boolean b):显示或隐藏此窗体具体取决于参数b的值
- void setSize(int width, int height):调整此组件的大小,使其宽度为width,高度为height,单位是像素
import javax.swing.*;
/*
构造方法
JFrame():构造一个最初不可见的新窗体
成员方法
void setVisible(boolean b):显示或隐藏此窗体具体取决于参数b的值
void setSize(int width, int height):调整此组件的大小,使其宽度为width,高度为height,单位是像素
*/
public class JFrameDemo01 {
public static void main(String[] args) {
//JFrame():构造一个最初不可见的新窗体
JFrame jf = new JFrame();
//void setSize(int width, int height):调整此组件的大小,使其宽度为width,高度为height,单位是像素
jf.setSize(400, 300);
//void setVisible(boolean b):显示或隐藏此窗体具体取决于参数b的值
jf.setVisible(true);
}
}
4.2.2 JFrame(常用设置)
- void setTitle(String title):设置窗体标题
- void setLocationRelativeTo(Component c):设置位置,值为null,则窗体位于屏幕中央
- void setDefaultCloseOperation(int operation):设置窗体关闭时默认操作
- 整数3表示:窗口关闭时退出应用程序
- void setAlwaysOnTop(boolean alwaysOnTop):设置此窗口是否应始终位于其他窗口之上
import javax.swing.*;
/*
void setTitle(String title):设置窗体标题
void setLocationRelativeTo(Component c):设置位置,值为null,则窗体位于屏幕中央
void setDefaultCloseOperation(int operation):设置窗体关闭时默认操作(整数3表示:窗口关闭时退出应用
程序)
void setAlwaysOnTop(boolean alwaysOnTop):设置此窗口是否应始终位于其他窗口之上
*/
public class JFrameDemo02 {
public static void main(String[] args) {
//创建窗体对象
JFrame jf = new JFrame();
//void setTitle(String title):设置窗体标题
jf.setTitle("百度一下,你就知道");
//设置窗体大小
jf.setSize(400, 300);
//void setDefaultCloseOperation(int operation):设置窗体关闭时默认操作(整数3表示:窗口关闭时退出应用程序)
jf.setDefaultCloseOperation(3);
//void setLocationRelativeTo(Component c):设置位置,值为null,则窗体位于屏幕中央
jf.setLocationRelativeTo(null);
//void setAlwaysOnTop(boolean alwaysOnTop):设置此窗口是否应始终位于其他窗口之上
jf.setAlwaysOnTop(true);
//设置窗体可见
jf.setVisible(true);
}
}
4.2.3 JButton(窗口中添加按钮)
- JButton:
- 按钮的实现
- 构造方法:
- JButton(String text):创建一个带文本的按钮
- 成员方法:
- void setSize(int width, int height):设置大小
- void setLocation(int x, int y):设置位置(x坐标,y坐标)
- void setBounds(int x, int y, int width, int height):设置位置和大小
- 和窗体相关操作:
- 取消窗体默认布局:窗体对象.setLayout(null);
- 把按钮添加到窗体:窗体对象.add(按钮对象);
import javax.swing.*;
/*
构造方法
JButton(String text):创建一个带文本的按钮
成员方法
void setSize(int width, int height):设置大小
void setLocation(int x, int y):设置位置(x坐标,y坐标)
*/
public class JButtonDemo {
public static void main(String[] args) {
//创建窗体对象
JFrame jf = new JFrame();
jf.setTitle("窗口中添加按钮");
jf.setSize(400, 300);
jf.setDefaultCloseOperation(3);
jf.setLocationRelativeTo(null);
jf.setAlwaysOnTop(true);
jf.setLayout(null); //取消窗体的默认布局
//JButton(String text):创建一个带文本的按钮
JButton btn = new JButton("我是按钮");
// //void setSize(int width, int height):设置大小
// btn.setSize(100,20);
// //void setLocation(int x, int y):设置位置(x坐标,y坐标)
btn.setLocation(0,0);
// btn.setLocation(100,100);
btn.setBounds(100, 100, 100, 20);
JButton btn2 = new JButton("我是按钮2");
btn2.setBounds(100, 120, 100, 20);
jf.add(btn);
jf.add(btn2);
//设置窗体可见
jf.setVisible(true);
}
}
4.2.4 JLabel(显示文本和图像)
- JLable:
- 短文本字符串或图像的显示区域
- 构造方法:
- JLabel(String text):使用指定的文本创建 JLabel实例
- JLabel(Icon image):使用指定的图像创建 JLabel实例
- ImageIcon(String filename):从指定的文件创建ImageIcon
- 文件路径:绝对路径和相对路径
- 绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件
例如:D:\IdeaProjects\javase_code\itheima-api-gui\images\mn.png - 相对路径:必须使用取自其他路径名的信息进行解释
例如:itheima-api-gui\images\mn.png
- 成员方法:
- void setBounds(int x, int y, int width, int height):设置位置和大小
import javax.swing.*;
/*
构造方法
JLabel(String text):使用指定的文本创建 JLabel实例
JLabel(Icon image):使用指定的图像创建 JLabel实例
ImageIcon(String filename):从指定的文件创建ImageIcon
成员方法
void setBounds(int x, int y, int width, int height):设置位置和大小
*/
public class JLabelDemo {
public static void main(String[] args) {
//创建窗体对象
JFrame jf = new JFrame();
jf.setTitle("显示文本和图像");
jf.setSize(400, 300);
jf.setDefaultCloseOperation(3);
jf.setLocationRelativeTo(null);
jf.setAlwaysOnTop(true);
jf.setLayout(null);
//JLabel(String text):使用指定的文本创建 JLabel实例
JLabel jLabel = new JLabel("好好学习");
jLabel.setBounds(0, 0, 100, 20);
//JLabel(Icon image):使用指定的图像创建 JLabel实例
//ImageIcon(String filename):从指定的文件创建ImageIcon
//D:\IdeaProjects\javase_code\itheima-api-gui\images\mn.png
// ImageIcon imageIcon = new ImageIcon("D:\\IdeaProjects\\javase_code\\itheima-apigui\\images\\mn.png");
// JLabel jLabel2 = new JLabel(imageIcon);
// JLabel jLabel2 = new JLabel(new ImageIcon("D:\\IdeaProjects\\javase_code\\itheimaapi-gui\\images\\mn.png"));
JLabel jLabel2 = new JLabel(new ImageIcon("itheima-api-gui\\images\\mn.png"));
jLabel2.setBounds(50, 50, 100, 143);
jf.add(jLabel);
jf.add(jLabel2);
//设置窗体可见
jf.setVisible(true);
}
}
4.3 案例
使用GUI中的常用组件把界面做出来
4.3.1 案例1(用户登录)
分析:
① 2个JLabel
② 2个JTextField
③ 1个JButton
引入了一个新的组件JPasswordField,用来表示密码框。
import javax.swing.*;
/*
用户登录
*/
public class UserLogin {
public static void main(String[] args) {
//创建窗体对象
JFrame jf = new JFrame();
//窗体标题
jf.setTitle("用户登录");
//窗体大小
jf.setSize(400, 300);
//窗口关闭时退出应用程序
jf.setDefaultCloseOperation(3);
//设置位置,值为null,则窗体位于屏幕中央
jf.setLocationRelativeTo(null);
//设置此窗口是否应始终位于其他窗口之上
jf.setAlwaysOnTop(true);
//取消窗体默认布局
jf.setLayout(null);
//显示用户名文本
JLabel usernamelabel = new JLabel("用户名");
//设置位置和大小
usernamelabel.setBounds(50, 50, 50, 20);
//用户名输入框
JTextField usernameField = new JTextField();
//设置位置和大小
usernameField.setBounds(150, 50, 180, 20);
//显示用户名文本
JLabel passwordlabel = new JLabel("密码");
//设置位置和大小
passwordlabel.setBounds(50, 100, 50, 20);
//密码输入框
// JTextField passwordField = new JTextField();
//设置位置和大小
// passwordField.setBounds(150, 100, 180, 20);
//JPasswordField用来表示密码框
JPasswordField passwordField = new JPasswordField();
passwordField.setBounds(150,100,180,20);
//登录按钮
JButton loginButton = new JButton("登录");
//设置位置和大小
loginButton.setBounds(50,200,280,20);
//显示窗体
jf.setVisible(true);
//把按钮添加到窗体
jf.add(usernamelabel);
jf.add(passwordlabel);
jf.add(usernameField);
jf.add(passwordField);
jf.add(loginButton);
}
}
4.3.2 案例2(聊天室)
分析:
① 1个JTextArea
② 1个JTextField
③ 2个JButton
引入了一个新的组件JTextArea,用来表示文本域。
import javax.swing.*;
/*
聊天室
*/
public class ChatRoom {
public static void main(String[] args) {
JFrame jf = new JFrame();
jf.setTitle("聊天室");
jf.setSize(400, 300);
jf.setDefaultCloseOperation(3);
jf.setLocationRelativeTo(null);
jf.setAlwaysOnTop(true);
jf.setLayout(null);
//显示聊天信息的文本域
JTextArea messageArea = new JTextArea();
messageArea.setBounds(10, 10, 360, 200);
//输入聊天信息的文本框
JTextField messageField = new JTextField();
messageField.setBounds(10, 230, 180, 20);
//发送按钮
JButton sendButton = new JButton("发送");
sendButton.setBounds(200, 230, 70, 20);
//清空聊天按钮
JButton clearButton = new JButton("清空聊天");
clearButton.setBounds(280, 230, 100, 20);
jf.setVisible(true);
jf.add(clearButton);
jf.add(messageArea);
jf.add(messageField);
jf.add(sendButton);
}
}
4.3.3 案例3(猜数字)
分析:
① 1个JLabel
② 1个JTextField
③ 1个JButton
import javax.swing.*;
/*
猜数字
*/
public class GuessNumber {
public static void main(String[] args) {
//创建窗体对象
JFrame jf = new JFrame();
jf.setTitle("猜数字");
jf.setSize(400, 300);
jf.setDefaultCloseOperation(3);
jf.setLocationRelativeTo(null);
jf.setAlwaysOnTop(true);
jf.setLayout(null);
//提示信息
JLabel messageLable = new JLabel("系统产生了一个1-100之间的数据,请猜一猜");
messageLable.setBounds(70, 50, 350, 20);
//输入要猜的数字
JTextField numberField = new JTextField();
numberField.setBounds(120, 100, 150, 20);
//猜数字的按钮
JButton guessButton = new JButton("我猜");
guessButton.setBounds(150, 150, 100, 20);
jf.setVisible(true);
jf.add(messageLable);
jf.add(numberField);
jf.add(guessButton);
}
}
4.3.4 案例4(手机日期和时间显示)
分析:
① 4个JLabel
import javax.swing.*;
/*
手机日期和时间显示
*/
public class ShowDateTime {
public static void main(String[] args) {
//创建窗体对象
JFrame jf = new JFrame();
jf.setTitle("手机日期和时间显示");
jf.setSize(400, 300);
jf.setDefaultCloseOperation(3);
jf.setLocationRelativeTo(null);
jf.setAlwaysOnTop(true);
jf.setLayout(null);
//提示日期
JLabel dateLable = new JLabel("日期");
dateLable.setBounds(50, 50, 100, 20);
//按照格式显示日期的字符串
JLabel showDateLable = new JLabel("xxxx年xx月xx日");
showDateLable.setBounds(50, 80, 200, 20);
//提示时间
JLabel timeLable = new JLabel("时间");
timeLable.setBounds(50, 150, 100, 20);
//按照格式显示时间的字符串
JLabel showTimeLable = new JLabel("xx:xx");
showTimeLable.setBounds(50, 180, 200, 20);
jf.setVisible(true);
jf.add(dateLable);
jf.add(showDateLable);
jf.add(timeLable);
jf.add(showTimeLable);
}
}
4.3.5 案例5(考勤查询)
分析:
① 3个JLabel
② 2个JTextField
③ 1个JButton
import javax.swing.*;
/*
考勤查询
*/
public class AttendanceQuery01 {
public static void main(String[] args) {
//创建窗体对象
JFrame jf = new JFrame();
jf.setTitle("考勤查询");
jf.setSize(400, 300);
jf.setDefaultCloseOperation(3);
jf.setLocationRelativeTo(null);
jf.setAlwaysOnTop(true);
jf.setLayout(null);
//显示考勤日期的文本
JLabel dateLable = new JLabel("考勤日期");
dateLable.setBounds(50, 20, 100, 20);
//显示开始时间文本
JLabel startDateLable = new JLabel("开始时间");
startDateLable.setBounds(50, 70, 100, 20);
//开始时间输入框
JTextField startDateField = new JTextField();
startDateField.setBounds(50, 100, 100, 20);
//显示结束时间文本
JLabel endDateLable = new JLabel("结束时间");
endDateLable.setBounds(250, 70, 100, 20);
//结束时间输入框
JTextField endDateField = new JTextField();
endDateField.setBounds(250, 100, 100, 20);
//确定按钮
JButton confirmButton = new JButton("确定");
confirmButton.setBounds(250, 180, 60, 20);
jf.setVisible(true);
jf.add(dateLable);
jf.add(startDateLable);
jf.add(startDateField);
jf.add(endDateLable);
jf.add(endDateField);
jf.add(confirmButton);
}
}
4.3.6 案例5(考勤查询之日历控件)
import javax.swing.*;
/*
考勤查询
*/
public class AttendanceQuery02 {
public static void main(String[] args) {
//创建窗体对象
JFrame jf = new JFrame();
jf.setTitle("考勤查询");
jf.setSize(400, 300);
jf.setDefaultCloseOperation(3);
jf.setLocationRelativeTo(null);
jf.setAlwaysOnTop(true);
jf.setLayout(null);
//显示考勤日期的文本
JLabel dateLable = new JLabel("考勤日期");
dateLable.setBounds(50, 20, 100, 20);
jf.add(dateLable);
//显示开始时间文本
JLabel startDateLable = new JLabel("开始时间");
startDateLable.setBounds(50, 70, 100, 20);
jf.add(startDateLable);
DateChooser dateChooser1 = DateChooser.getInstance("yyyy/MM/dd");
DateChooser dateChooser2 = DateChooser.getInstance("yyyy/MM/dd");
//开始时间输入框
JTextField startDateField = new JTextField();
startDateField.setBounds(50, 100, 100, 20);
dateChooser1.register(startDateField);
jf.add(startDateField);
//显示结束时间文本
JLabel endDateLable = new JLabel("结束时间");
endDateLable.setBounds(250, 70, 100, 20);
jf.add(endDateLable);
//结束时间输入框
JTextField endDateField = new JTextField();
endDateField.setBounds(250, 100, 100, 20);
dateChooser2.register(endDateField);
jf.add(endDateField);
//确定按钮
JButton confirmButton = new JButton("确定");
confirmButton.setBounds(250, 180, 60, 20);
jf.add(confirmButton);
jf.setVisible(true);
}
}
4.4 事件监听机制
我们做了GUI的界面,但是具体的功能我们没法实现。因为要想实现功能就必须要学习一下事件监听机制。
事件监听机制的组成:
- 事件源:事件发生的地方。可以是按钮,窗体,图片等
- 事件:发生了什么事情。例如:鼠标点击事件,键盘按下事件等
- 事件绑定:把事件绑定到事件源上,当发生了某个事件,则触发对应的处理逻辑
- 事件源对象. addXXXListener(事件);
GUI中的事件比较多,我们先学习如何给按钮添加事件,能够把之前案例给实现。
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/*
事件监听机制
*/
public class ActionListenerDemo {
public static void main(String[] args) {
//创建窗体对象
JFrame jf = new JFrame();
jf.setTitle("事件监听机制");
jf.setSize(400, 300);
jf.setDefaultCloseOperation(3);
jf.setLocationRelativeTo(null);
jf.setAlwaysOnTop(true);
jf.setLayout(null);
//创建按钮
JButton jButton = new JButton("你点我啊");
jButton.setBounds(0, 0, 100, 100);
jf.add(jButton);
jButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("你点我啊");
}
});
jf.setVisible(true);
}
}
扩展-4.3.6 案例5(考勤查询之日历控件)
日历控件类(DateChooser.java) 借用大佬写完的
import javax.swing.*;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import java.awt.*;
import java.awt.event.*;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;
/**
* 日期选择器,可以指定日期的显示格式
*/
public class DateChooser extends JPanel {
private static final long serialVersionUID = 4529266044762990227L;
private Date initDate;
private Calendar now = Calendar.getInstance();
private Calendar select;
private JPanel monthPanel;// 月历
private JP1 jp1;// 四块面板,组成
private JP2 jp2;
private JP3 jp3;
private JP4 jp4;
private Font font = new Font("宋体", Font.PLAIN, 12);
private final LabelManager lm = new LabelManager();
private SimpleDateFormat sdf;
private boolean isShow = false;
private Popup pop;
private JComponent showDate;
public static DateChooser getInstance() {
return new DateChooser();
}
public static DateChooser getInstance(Date date) {
return new DateChooser(date);
}
public static DateChooser getInstance(String format) {
return new DateChooser(format);
}
public static DateChooser getInstance(Date date, String format) {
return new DateChooser(date, format);
}
/**
* Creates a new instance of DateChooser
*/
private DateChooser() {
this(new Date());
}
private DateChooser(Date date) {
this(date, "yyyy年MM月dd日");
}
private DateChooser(String format) {
this(new Date(), format);
}
private DateChooser(Date date, String format) {
initDate = date;
sdf = new SimpleDateFormat(format);
select = Calendar.getInstance();
select.setTime(initDate);
initPanel();
}
/**
* 是否允许用户选择
*/
public void setEnabled(boolean b) {
super.setEnabled(b);
showDate.setEnabled(b);
}
/**
* 得到当前选择框的日期
*/
public Date getDate() {
return select.getTime();
}
public String getStrDate() {
return sdf.format(select.getTime());
}
public String getStrDate(String format) {
sdf = new SimpleDateFormat(format);
return sdf.format(select.getTime());
}
// 根据初始化的日期,初始化面板
private void initPanel() {
monthPanel = new JPanel(new BorderLayout());
monthPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
JPanel up = new JPanel(new BorderLayout());
up.add(jp1 = new JP1(), BorderLayout.NORTH);
up.add(jp2 = new JP2(), BorderLayout.CENTER);
monthPanel.add(jp3 = new JP3(), BorderLayout.CENTER);
monthPanel.add(up, BorderLayout.NORTH);
monthPanel.add(jp4 = new JP4(), BorderLayout.SOUTH);
this.addAncestorListener(new AncestorListener() {
public void ancestorAdded(AncestorEvent event) {
}
public void ancestorRemoved(AncestorEvent event) {
}
// 只要祖先组件一移动,马上就让popup消失
public void ancestorMoved(AncestorEvent event) {
hidePanel();
}
});
}
public void register(final JComponent showDate) {
this.showDate = showDate;
showDate.setRequestFocusEnabled(true);
showDate.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
showDate.requestFocusInWindow();
}
});
this.setBackground(Color.WHITE);
this.add(showDate, BorderLayout.CENTER);
this.setPreferredSize(new Dimension(90, 25));
this.setBorder(BorderFactory.createLineBorder(Color.GRAY));
showDate.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent me) {
if (showDate.isEnabled()) {
showDate.setCursor(new Cursor(Cursor.HAND_CURSOR));
showDate.setForeground(Color.RED);
}
}
public void mouseExited(MouseEvent me) {
if (showDate.isEnabled()) {
showDate.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
showDate.setForeground(Color.BLACK);
}
}
public void mousePressed(MouseEvent me) {
if (showDate.isEnabled()) {
showDate.setForeground(Color.CYAN);
if (isShow) {
hidePanel();
} else {
showPanel(showDate);
}
}
}
public void mouseReleased(MouseEvent me) {
if (showDate.isEnabled()) {
showDate.setForeground(Color.BLACK);
}
}
});
showDate.addFocusListener(new FocusListener() {
public void focusLost(FocusEvent e) {
hidePanel();
}
public void focusGained(FocusEvent e) {
}
});
}
// 根据新的日期刷新
private void refresh() {
jp1.updateDate();
jp2.updateDate();
jp3.updateDate();
jp4.updateDate();
SwingUtilities.updateComponentTreeUI(this);
}
// 提交日期
private void commit() {
// TODO add other components here
if (showDate instanceof JTextField) {
((JTextField) showDate).setText(sdf.format(select.getTime()));
} else if (showDate instanceof JLabel) {
((JLabel) showDate).setText(sdf.format(select.getTime()));
}
hidePanel();
}
// 隐藏日期选择面板
private void hidePanel() {
if (pop != null) {
isShow = false;
pop.hide();
pop = null;
}
}
// 显示日期选择面板
private void showPanel(Component owner) {
if (pop != null) {
pop.hide();
}
Point show = new Point(0, showDate.getHeight());
SwingUtilities.convertPointToScreen(show, showDate);
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
int x = show.x;
int y = show.y;
if (x < 0) {
x = 0;
}
if (x > size.width - 295) {
x = size.width - 295;
}
if (y < size.height - 170) {
} else {
y -= 188;
}
pop = PopupFactory.getSharedInstance()
.getPopup(owner, monthPanel, x, y);
pop.show();
isShow = true;
}
/**
* 最上面的面板用来显示月份的增减
*/
private class JP1 extends JPanel {
private static final long serialVersionUID = -5638853772805561174L;
JLabel yearleft, yearright, monthleft, monthright, center,
centercontainer;
public JP1() {
super(new BorderLayout());
this.setBackground(new Color(160, 185, 215));
initJP1();
}
private void initJP1() {
yearleft = new JLabel(" <<", JLabel.CENTER);
yearleft.setToolTipText("上一年");
yearright = new JLabel(">> ", JLabel.CENTER);
yearright.setToolTipText("下一年");
yearleft.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
yearright.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 0));
monthleft = new JLabel(" <", JLabel.RIGHT);
monthleft.setToolTipText("上一月");
monthright = new JLabel("> ", JLabel.LEFT);
monthright.setToolTipText("下一月");
monthleft.setBorder(BorderFactory.createEmptyBorder(2, 30, 0, 0));
monthright.setBorder(BorderFactory.createEmptyBorder(2, 0, 0, 30));
centercontainer = new JLabel("", JLabel.CENTER);
centercontainer.setLayout(new BorderLayout());
center = new JLabel("", JLabel.CENTER);
centercontainer.add(monthleft, BorderLayout.WEST);
centercontainer.add(center, BorderLayout.CENTER);
centercontainer.add(monthright, BorderLayout.EAST);
this.add(yearleft, BorderLayout.WEST);
this.add(centercontainer, BorderLayout.CENTER);
this.add(yearright, BorderLayout.EAST);
this.setPreferredSize(new Dimension(295, 25));
updateDate();
yearleft.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent me) {
yearleft.setCursor(new Cursor(Cursor.HAND_CURSOR));
yearleft.setForeground(Color.RED);
}
public void mouseExited(MouseEvent me) {
yearleft.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
yearleft.setForeground(Color.BLACK);
}
public void mousePressed(MouseEvent me) {
select.add(Calendar.YEAR, -1);
yearleft.setForeground(Color.WHITE);
refresh();
}
public void mouseReleased(MouseEvent me) {
yearleft.setForeground(Color.BLACK);
}
});
yearright.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent me) {
yearright.setCursor(new Cursor(Cursor.HAND_CURSOR));
yearright.setForeground(Color.RED);
}
public void mouseExited(MouseEvent me) {
yearright.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
yearright.setForeground(Color.BLACK);
}
public void mousePressed(MouseEvent me) {
select.add(Calendar.YEAR, 1);
yearright.setForeground(Color.WHITE);
refresh();
}
public void mouseReleased(MouseEvent me) {
yearright.setForeground(Color.BLACK);
}
});
monthleft.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent me) {
monthleft.setCursor(new Cursor(Cursor.HAND_CURSOR));
monthleft.setForeground(Color.RED);
}
public void mouseExited(MouseEvent me) {
monthleft.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
monthleft.setForeground(Color.BLACK);
}
public void mousePressed(MouseEvent me) {
select.add(Calendar.MONTH, -1);
monthleft.setForeground(Color.WHITE);
refresh();
}
public void mouseReleased(MouseEvent me) {
monthleft.setForeground(Color.BLACK);
}
});
monthright.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent me) {
monthright.setCursor(new Cursor(Cursor.HAND_CURSOR));
monthright.setForeground(Color.RED);
}
public void mouseExited(MouseEvent me) {
monthright.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
monthright.setForeground(Color.BLACK);
}
public void mousePressed(MouseEvent me) {
select.add(Calendar.MONTH, 1);
monthright.setForeground(Color.WHITE);
refresh();
}
public void mouseReleased(MouseEvent me) {
monthright.setForeground(Color.BLACK);
}
});
}
private void updateDate() {
center.setText(select.get(Calendar.YEAR) + "年"
+ (select.get(Calendar.MONTH) + 1) + "月");
}
}
private class JP2 extends JPanel {
private static final long serialVersionUID = -8176264838786175724L;
public JP2() {
this.setPreferredSize(new Dimension(295, 20));
}
protected void paintComponent(Graphics g) {
g.setFont(font);
g.drawString("星期日 星期一 星期二 星期三 星期四 星期五 星期六", 5, 10);
g.drawLine(0, 15, getWidth(), 15);
}
private void updateDate() {
}
}
private class JP3 extends JPanel {
private static final long serialVersionUID = 43157272447522985L;
public JP3() {
super(new GridLayout(6, 7));
this.setPreferredSize(new Dimension(295, 100));
initJP3();
}
private void initJP3() {
updateDate();
}
public void updateDate() {
this.removeAll();
lm.clear();
Date temp = select.getTime();
Calendar select = Calendar.getInstance();
select.setTime(temp);
select.set(Calendar.DAY_OF_MONTH, 1);
int index = select.get(Calendar.DAY_OF_WEEK);
int sum = (index == 1 ? 8 : index);
select.add(Calendar.DAY_OF_MONTH, 0 - sum);
for (int i = 0; i < 42; i++) {
select.add(Calendar.DAY_OF_MONTH, 1);
lm.addLabel(new MyLabel(select.get(Calendar.YEAR), select
.get(Calendar.MONTH), select.get(Calendar.DAY_OF_MONTH)));
}
for (MyLabel my : lm.getLabels()) {
this.add(my);
}
select.setTime(temp);
}
}
private class MyLabel extends JLabel implements Comparator<MyLabel>,
MouseListener, MouseMotionListener {
private static final long serialVersionUID = 3668734399227577214L;
private int year, month, day;
private boolean isSelected;
public MyLabel(int year, int month, int day) {
super("" + day, JLabel.CENTER);
this.year = year;
this.day = day;
this.month = month;
this.addMouseListener(this);
this.addMouseMotionListener(this);
this.setFont(font);
if (month == select.get(Calendar.MONTH)) {
this.setForeground(Color.BLACK);
} else {
this.setForeground(Color.LIGHT_GRAY);
}
if (day == select.get(Calendar.DAY_OF_MONTH)) {
this.setBackground(new Color(160, 185, 215));
} else {
this.setBackground(Color.WHITE);
}
}
public boolean getIsSelected() {
return isSelected;
}
public void setSelected(boolean b, boolean isDrag) {
isSelected = b;
if (b && !isDrag) {
int temp = select.get(Calendar.MONTH);
select.set(year, month, day);
if (temp == month) {
SwingUtilities.updateComponentTreeUI(jp3);
} else {
refresh();
}
}
this.repaint();
}
protected void paintComponent(Graphics g) {
if (day == select.get(Calendar.DAY_OF_MONTH)
&& month == select.get(Calendar.MONTH)) {
// 如果当前日期是选择日期,则高亮显示
g.setColor(new Color(160, 185, 215));
g.fillRect(0, 0, getWidth(), getHeight());
}
if (year == now.get(Calendar.YEAR)
&& month == now.get(Calendar.MONTH)
&& day == now.get(Calendar.DAY_OF_MONTH)) {
// 如果日期和当前日期一样,则用红框
Graphics2D gd = (Graphics2D) g;
gd.setColor(Color.RED);
Polygon p = new Polygon();
p.addPoint(0, 0);
p.addPoint(getWidth() - 1, 0);
p.addPoint(getWidth() - 1, getHeight() - 1);
p.addPoint(0, getHeight() - 1);
gd.drawPolygon(p);
}
if (isSelected) {// 如果被选中了就画出一个虚线框出来
Stroke s = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE,
BasicStroke.JOIN_BEVEL, 1.0f,
new float[]{2.0f, 2.0f}, 1.0f);
Graphics2D gd = (Graphics2D) g;
gd.setStroke(s);
gd.setColor(Color.BLACK);
Polygon p = new Polygon();
p.addPoint(0, 0);
p.addPoint(getWidth() - 1, 0);
p.addPoint(getWidth() - 1, getHeight() - 1);
p.addPoint(0, getHeight() - 1);
gd.drawPolygon(p);
}
super.paintComponent(g);
}
public boolean contains(Point p) {
return this.getBounds().contains(p);
}
private void update() {
repaint();
}
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
isSelected = true;
update();
}
public void mouseReleased(MouseEvent e) {
Point p = SwingUtilities.convertPoint(this, e.getPoint(), jp3);
lm.setSelect(p, false);
commit();
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseDragged(MouseEvent e) {
Point p = SwingUtilities.convertPoint(this, e.getPoint(), jp3);
lm.setSelect(p, true);
}
public void mouseMoved(MouseEvent e) {
}
public int compare(MyLabel o1, MyLabel o2) {
Calendar c1 = Calendar.getInstance();
c1.set(o1.year, o2.month, o1.day);
Calendar c2 = Calendar.getInstance();
c2.set(o2.year, o2.month, o2.day);
return c1.compareTo(c2);
}
}
private class LabelManager {
private List<MyLabel> list;
public LabelManager() {
list = new ArrayList<MyLabel>();
}
public List<MyLabel> getLabels() {
return list;
}
public void addLabel(MyLabel my) {
list.add(my);
}
public void clear() {
list.clear();
}
@SuppressWarnings("unused")
public void setSelect(MyLabel my, boolean b) {
for (MyLabel m : list) {
if (m.equals(my)) {
m.setSelected(true, b);
} else {
m.setSelected(false, b);
}
}
}
public void setSelect(Point p, boolean b) {
// 如果是拖动,则要优化一下,以提高效率
if (b) {
// 表示是否能返回,不用比较完所有的标签,能返回的标志就是把上一个标签和
// 将要显示的标签找到了就可以了
boolean findPrevious = false, findNext = false;
for (MyLabel m : list) {
if (m.contains(p)) {
findNext = true;
if (m.getIsSelected()) {
findPrevious = true;
} else {
m.setSelected(true, b);
}
} else if (m.getIsSelected()) {
findPrevious = true;
m.setSelected(false, b);
}
if (findPrevious && findNext) {
return;
}
}
} else {
MyLabel temp = null;
for (MyLabel m : list) {
if (m.contains(p)) {
temp = m;
} else if (m.getIsSelected()) {
m.setSelected(false, b);
}
}
if (temp != null) {
temp.setSelected(true, b);
}
}
}
}
private class JP4 extends JPanel {
private static final long serialVersionUID = -6391305687575714469L;
public JP4() {
super(new BorderLayout());
this.setPreferredSize(new Dimension(295, 20));
this.setBackground(new Color(160, 185, 215));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
final JLabel jl = new JLabel("今天: " + sdf.format(new Date()));
jl.setToolTipText("点击选择今天日期");
this.add(jl, BorderLayout.CENTER);
jl.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent me) {
jl.setCursor(new Cursor(Cursor.HAND_CURSOR));
jl.setForeground(Color.RED);
}
public void mouseExited(MouseEvent me) {
jl.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
jl.setForeground(Color.BLACK);
}
public void mousePressed(MouseEvent me) {
jl.setForeground(Color.WHITE);
select.setTime(new Date());
refresh();
commit();
}
public void mouseReleased(MouseEvent me) {
jl.setForeground(Color.BLACK);
}
});
}
private void updateDate() {
}
}
public static void main(String[] args) {
//创建窗体
JFrame jf = new JFrame();
//设置窗体大小
jf.setSize(400, 300);
//设置窗体标题
jf.setTitle("日历控件");
//设置位置,值为null,则窗体位于屏幕中央
jf.setLocationRelativeTo(null);
//设置窗体关闭时默认操作,窗口关闭时退出应用程序
jf.setDefaultCloseOperation(3);
//设置此窗口是否应始终位于其他窗口之上
jf.setAlwaysOnTop(true);
//取消窗体默认布局:窗体对象.setLayout(null);
jf.setLayout(null);
//创建日期选择器对象,指定日期字符串格式
DateChooser dateChooser = DateChooser.getInstance("yyyy-MM-dd");
JTextField showDateField = new JTextField("单击选择日期");
showDateField.setBounds(50, 50, 100, 20);
//把日历控件和文本框进行绑定
dateChooser.register(showDateField);
jf.add(showDateField);
jf.setVisible(true);
}
}