一、代码块
1、代码块是类的五大成分之一(成员变量、构造器、方法、代码块、内部类)。
2、代码块分为两种:
- 静态代码块:
- 格式:static{ }
- 特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也只会执行一次。
- 作用:完成类的初始化,例如:对静态变量的初始化赋值。
- 实例代码块:
- 格式:{ }
- 特点:每次创建对象时,执行实例代码块,并在构造器前执行。
- 作用:和构造器一样,都是用来完成对象的初始化的,例如:对实例变量的初始化赋值。
import java.util.Arrays;
public class CodeDemo1 {
public static String schoolName;
public static String[] cards=new String[54];
//静态代码块:有static修饰,属于类,与类一起优先加载,自动执行一次
//基本作用:可以完成对类的静态资源的初始化
static{
System.out.println("静态代码块");
schoolName = "黑马程序员";
cards[0]="大王";
cards[1]="小王";
//...
}
public static void main(String[] args)
{
//认识代码块,搞清楚代码块的基本作用
System.out.println("main方法");
System.out.println(schoolName);
System.out.println(Arrays.toString(cards));
}
}
public class CodeDemo2 {
private String name;
private String[] direction=new String[4];
//实例代码块:无static修饰,属于对象,每次创建对象时,都会优先执行一次
//基本作用:初始化对象的实例资源
{
System.out.println("实例代码块");
name="黑马";
direction[0]="东";
direction[1]="南";
direction[2]="西";
direction[3]="北";
}
public static void main(String[] args)
{
//实例代码块
System.out.println("main方法");
CodeDemo2 c=new CodeDemo2();
CodeDemo2 c2=new CodeDemo2();
}
}
二、内部类
如果一个类定义在另一个类的内部,这个类就是内部类。
场景:当一个类的内部,包含了一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类。
1、成员内部类
就是类中的一个普通成员,类似前面学过的普通的成员变量、成员方法。
创建成员内部类对象格式:外部类名.内部类名 对象名=new 外部类名() .new 内部类名();
成员内部类中访问其他成员的特点:
- 成员内部类中可以直接访问外部类的实例成员、静态成员。
- 成员内部类的实例方法中,可以直接拿到当前外部类对象,格式是:外部类名.this.成员名。
//外部类
public class Outter {
public static String schoolName="黑马程序员";
public static void test(){
System.out.println("test()");
}
private int age;
public void run(){
System.out.println("run()");
}
//成员内部类:无static修饰,属于外部类的对象持有的
public class Inner{
private String name;
//构造器
public Inner(){
System.out.println("Inner()"+name);
}
//有参数构造器
public Inner(String name){
this.name=name;
System.out.println("Inner(String name)"+name);
}
public void show(){
System.out.println("show");
System.out.println(schoolName);
test();
System.out.println(age);
run();
System.out.println(this);//自己的对象
System.out.println(Outter.this);//寄生的外部类的对象
}
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
}
}
public class InnerClassDemo1 {
public static void main(String[] args)
{
//搞清楚成员内部类的语法
//成员内部类创建对象的格式
//外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
Outter.Inner oi = new Outter().new Inner();
oi.setName("小明");
oi.show();
//成员内部类访问外部类成员的特点
//1、成员内部类中可以直接访问外部类的静态成员,也可以直接访问外部类的实例成员
//2、成员内部类的实例方法中,可以直接拿到当前寄生的外部类对象:外部类名.this
People.Heart h=new People().new Heart();
h.show();
}
}
class People{
private int heartBeat=100;
public class Heart{
private int heartBeat=80;
public void show(){
int heartBeat=200;
System.out.println(heartBeat);//200
System.out.println(this.heartBeat);//80
System.out.println(People.this.heartBeat);//100
}
}
}
2、静态内部类
有static修饰的内部类,属于外部类自己持有。
创建静态内部类对象格式:外部类名.内部类名 对象名=new 外部类.内部类名();
静态内部类中访问外部类成员的特点:
- 可以直接访问外部类的静态成员,不可以直接访问外部类的实例成员。
//外部类
public class Outer {
public static String schoolName="黑马程序员";
private int age;//实例成员
//静态内部类:属于外部类本身持有
public static class Inner{
public void show() {
System.out.println("show");
System.out.println(schoolName);
//System.out.println(age);//报错
}
}
}
public class InnerClassDemo2 {
public static void main(String[] args) {
//搞清楚静态内部类的语法
//创建对象:外部类名.内部类名 对象名= new 外部类名称.内部类名称();
Outer.Inner oi=new Outer.Inner();
oi.show();
//静态内部类中是否可以直接访问外部类的静态成员?可以
//静态内部类中是否可以直接访问外部类的实例成员?不可以
}
}
3、局部内部类
局部内部类是定义在方法中、代码块中、构造器等执行体中(无具体意义,用来引出匿名内部类)。
4、匿名内部类
特殊的局部内部类,匿名内部类指:程序员不需要为这个类声明名字,默认有一个隐藏的名字。
格式:new 类名或接口(参数值...){重写方法}
特点:匿名内部类本质就是一个子类,并会立即创建出一个子类对象。
作用:用于更方便的创建一个子类对象。
public abstract class Animal {
public abstract void cry();
}
public class Test {
public static void main(String[] args)
{
//认识匿名内部类,搞清楚其基本作用
//匿名内部类实际上是有名字的:外部类名$编号.class
//匿名内部类本质是一个子类,同时会立即创建一个子类对象
Animal a=new Animal(){
@Override
public void cry()
{
System.out.println("猫是喵喵喵的叫");
}
};
a.cry();
}
}
//class Cat extends Animal{
//
// @Override
// public void cry() {
// System.out.println("猫是喵喵喵的叫");
// }
//}
通常作为一个对象参数传输给方法。
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;
private int age;
private double height;
private char sex;
}
public class Test2 {
public static void main(String[] args)
{
//搞清楚匿名内部类的使用形式(语法):通常可以作为一个对象参数传输给方法使用
//需求:学生,老师都要参加游泳比赛
Swim s1=new Swim() {
@Override
public void swimming() {
System.out.println("学生蛙泳");
}
};
start(s1);
start(new Swim() {
@Override
public void swimming() {
System.out.println("老师狗爬式游泳");
}
});
}
//定义一个方法,可以接收老师和学生开始比赛
public static void start(Swim s){
System.out.println("比赛开始啦");
s.swimming();
System.out.println("比赛结束啦");
}
}
interface Swim{
void swimming();//游泳方法
}
匿名内部类应用场景:调用别人提供的方法实现需求时,这个方法正好可以让我们传输一个匿名内部类对象给其使用。
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test3 {
public static void main(String[] args)
{
//搞清楚几个匿名内部类的使用场景
//需求:创建一个登录窗口,窗口上只有一个登录按钮
JFrame win=new JFrame("登录界面");
win.setSize(300,200);
win.setLocationRelativeTo(null);//居中显示
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel=new JPanel();
win.add(panel);
JButton btn=new JButton("登录");
panel.add(btn);
//java要求必须给这个按钮添加一个点击事件监听器对象,这样就可以监听用户的点击操作,就可以做出反应
//开发中不是我们要主动去写匿名内部类,而是用别人的功能时,别人可以让我们写一个匿名内部类,我们才会用
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("用户点击了登录按钮");
}
});
win.setVisible(true);
}
}
import java.util.Arrays;
import java.util.Comparator;
public class Test4 {
public static void main(String[] args)
{
//完成给数组排序,理解其中匿名内部类的用法
//准备一个学生类型的数组,存放6个学生对象
Student[] students=new Student[6];
students[0]=new Student("张三",18,170, '男');
students[1]=new Student("李四",19,165, '女');
students[2]=new Student("王五",20,180, '男');
students[3]=new Student("赵六",21,175, '男');
students[4]=new Student("孙七",22,165, '女');
students[5]=new Student("周八",23,170, '男');
//需求:按照年龄升序排序。可以调用sun公司写好的API直接对数组进行排序
//public static void sort(T[] a, Comparator<T> c)
//参数一:需要排序的数组 参数二:需要给sort声明一个比较器对象(指定排序的规则)
//sort方法会调用匿名内部类对象的compare方法,对数组中的学生对象进行两两比较,从而实现排序
Arrays.sort(students,new Comparator<Student>(){
@Override
public int compare(Student o1, Student o2) {
//指定排序规则
//如果你认为左边对象 大于 右边对象 那么返回正整数
//如果你认为左边对象 小于 右边对象 那么返回负整数
//如果两边相等那么返回0
// if(o1.getAge() > o2.getAge()){
// return 1;
// }else if(o1.getAge() < o2.getAge()){
// return -1;
// }else{
// return 0;
// }
// return o1.getAge() - o2.getAge();//按照年龄升序
return o2.getAge() - o1.getAge();//按照年龄降序
}
});
//遍历数组中的学生对象并输出
for (int i = 0; i < students.length; i++) {
Student s=students[i];
System.out.println(s);
}
}
}
三、函数式编程
1、Java中的函数(即Lambda表达式)
JDK8开始引入了Lambda表达式,替代函数式接口的匿名内部类,从而让程序更简洁,可读性更好。
Lambda表达式的格式:(形式参数列表)->{匿名内部类被重写的方法体代码}
什么是函数式接口?
- 有且仅有一个抽象方法的接口。
- 注意:将来见到的大部分函数式接口,上面都可能会有一个@Functionallnterface的注解,该注解用于约束当前接口必须是函数式接口。
Lambda表达式的简化规则:
- 参数类型可以全部省略不写
- 如果只有一个参数,参数类型省略的同时"( )"也可以省略,但多个参数不能省略"( )"
- 如果Lambda表达式中只有一行代码,大括号可以不写,同时要省略分号,如果这行代码是return语句,也必须去掉return
public class LambdaDemo1 {
public static void main(String[] args) {
//认识Lambda表达式,搞清楚其基本作用
Animal a=new Animal() {
@Override
public void cry() {
System.out.println("猫是喵喵叫的");
}
};
a.cry();
//Lambda并不是可以简化全部的匿名内部类,Lambda只能简化函数式接口的匿名内部类
Swim s=()->{
System.out.println("Lambda简化的匿名内部类");
};
s.swimming();
}
}
abstract class Animal{
public abstract void cry();
}
//函数式接口:只有一个抽象方法的接口
@FunctionalInterface//声明函数式接口的注解
interface Swim{
void swimming();
}
import innerclass3.Student;
import java.util.Arrays;
public class LambdaDemo2 {
public static void main(String[] args) {
//用Lambda表达式简化实际示例
Student[] students=new Student[6];
students[0]=new Student("张三",18,170, '男');
students[1]=new Student("李四",19,165, '女');
students[2]=new Student("王五",20,180, '男');
students[3]=new Student("赵六",21,175, '男');
students[4]=new Student("孙七",22,165, '女');
students[5]=new Student("周八",23,170, '男');
//需求:按照年龄升序排序。可以调用sun公司写好的API直接对数组进行排序
// Arrays.sort(students,new Comparator<Student>(){
// @Override
// public int compare(Student o1, Student o2) {
// return o2.getAge() - o1.getAge();//按照年龄降序
// }
// });
// Arrays.sort(students,(Student o1, Student o2)->{
// return o2.getAge() - o1.getAge();//按照年龄降序
// });
// Arrays.sort(students,(o1,o2)->{
// return o2.getAge() - o1.getAge();//按照年龄降序
// });
Arrays.sort(students,(o1, o2)->o2.getAge() - o1.getAge());
//遍历数组中的学生对象并输出
for (int i = 0; i < students.length; i++) {
Student s=students[i];
System.out.println(s);
}
}
}
2、方法引用
JDK8中提供了一些常用的方法引用,可以用"::"引用运算符简化Lambda表达式
静态方法的引用
格式:类名::静态方法名
使用场景:如果某个Lambda表达式里只是调用一个静态方法,并且"->"前后参数的形式一致,就可以使用静态方法引用。
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;
private int age;
private double height;
private char sex;
public static int compareByAge(Student o1, Student o2)
{
return o1.getAge() - o2.getAge();
}
public int compareByHeight(Student o1, Student o2){
//按照身高比较
return Double.compare(o1.getHeight(), o2.getHeight());
}
}
import java.util.Arrays;
public class Demo1 {
public static void main(String[] args) {
// 静态方法引用:演示一个场景
test();
}
public static void test(){
Student[] students=new Student[6];
students[0]=new Student("张三",18,170, '男');
students[1]=new Student("李四",19,165, '女');
students[2]=new Student("王五",20,180, '男');
students[3]=new Student("赵六",21,175, '男');
students[4]=new Student("孙七",22,165, '女');
students[5]=new Student("周八",23,170, '男');
//需求:按照年龄升序排序。可以调用sun公司写好的API直接对数组进行排序
Arrays.sort(students,(o1, o2)->o2.getAge() - o1.getAge());
//静态方法引用:类名:静态方法名
Arrays.sort(students,Student::compareByAge);
//遍历数组中的学生对象并输出
for (int i = 0; i < students.length; i++) {
Student s=students[i];
System.out.println(s);
}
}
}
实例方法的引用
格式:对象名::实例方法名
使用场景:如果某个Lambda表达式里只是通过对象名称调用一个实例方法,并且"->"前后参数的形式一致,就可以使用实例方法引用。
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String name;
private int age;
private double height;
private char sex;
public static int compareByAge(Student o1, Student o2)
{
return o1.getAge() - o2.getAge();
}
public int compareByHeight(Student o1, Student o2){
//按照身高比较
return Double.compare(o1.getHeight(), o2.getHeight());
}
}
import java.util.Arrays;
public class Demo2 {
public static void main(String[] args) {
// 实例方法引用:演示一个场景
test();
}
public static void test(){
Student[] students=new Student[6];
students[0]=new Student("张三",18,170, '男');
students[1]=new Student("李四",19,165, '女');
students[2]=new Student("王五",20,180, '男');
students[3]=new Student("赵六",21,175, '男');
students[4]=new Student("孙七",22,165, '女');
students[5]=new Student("周八",23,170, '男');
//需求:按照年龄升序排序。可以调用sun公司写好的API直接对数组进行排序
Student t=new Student();
Arrays.sort(students,(o1, o2)->o2.getAge() - o1.getAge());
//Arrays.sort(students,Student::compareByHeight);
//遍历数组中的学生对象并输出
for (int i = 0; i < students.length; i++) {
Student s=students[i];
System.out.println(s);
}
}
}
特定类的方法引用
格式:特定类的名称::方法名
使用场景:如果某个Lambda表达式里只是调用一个特定类型的实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用。
构造器引用
格式:类名::new
使用场景:如果某个Lambda表达式里只是在创建对象,并且"->"前后参数情况一致,就可以使用构造器引用。
四、常见API
1、String
String是什么,有什么用?
- String代表字符串,它的对象可以封装字符串数据,并提供了很多方法完成对字符串的处理。
String类创建对象封装字符串数据的方式有几种?
- 方式一:直接使用双引号"..."。
- 方式二:new String类,调用构造器初始化字符串对象。
Attention:只要以双引号方式创建字符串对象,会存储到字符串常量池中,且相同字符串只会储存一次。通过new关键字创建字符串对象,每new一次,都会产生一个新的对象放在堆内存中。
import java.util.Scanner;
public class StringDemo1 {
public static void main(String[] args) {
//掌握创建字符串对象,封装要处理的字符串数据,调用String提供的方法处理字符串
//1、推荐方式一:直接""就可以创建字符串对象,封装字符串数据
String s1 = "hello,黑马";
System.out.println(s1);
System.out.println(s1.length());//处理字符串的方法
//2、方式二:通过构造器初始化对象
String s2 = new String();//不推荐
System.out.println(s2);//输出:空字符串
String s3 = new String("abc");//不推荐
System.out.println(s3);
char ch[] = {'a','b','c'};
String s4 = new String(ch);
System.out.println(s4);
byte b[] = {97,98,99};
String s5 = new String(b);
System.out.println(s5);
//只有双引号给出的字符串对象放在字符串常量池,相同内容只放一个
String t1="abc";
String t2="abc";
System.out.println(t1==t2);
String t3=new String("abc");
String t4=new String("abc");
System.out.println(t3==t4);
//调用字符串方法,处理字符串数据
//简易版登录
String username = "admin";
System.out.println("请输入您的登录名称:");
Scanner sc = new Scanner(System.in);
String name = sc.next();
//字符串对象的内容比较,千万不要用==默认比较地址,字符串对象的内容一样时地址不一定一样
//判断字符串内容,建议大家用String提供的equals方法,只关心内容一样,就返回true,不关心地址
if(name.equals(username)){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
//13546590922==》135****9022
System.out.println("请您用手机号码登录:");
String phone = sc.next();
System.out.println("系统显示以下手机号码进入:");
String newPhone = phone.substring(0,3)+"****"+phone.substring(7);
System.out.println(newPhone);
}
}
String提供的常用方法
方法名 | 说明 |
public int length() | 获取字符串长度返回(字符个数) |
public char cahrAt(int index) | 获取某个索引位置处的字符返回 |
public char[ ] toCharArray() | 将当前字符串转换成字符数组返回 |
public boolean equals(Object anObject) | 判断当前字符串与另一个字符串的内容是否一样,一样返回true |
public boolean equalsIgnoreCase(String anotherString) | 判断当前字符串与另一个字符串的内容是否一样(忽略大小写) |
public String substring(int beginIndex,int endIndex) | 根据开始和结束索引进行截取,得到新的字符串(包前不包后) |
public String substring(int beginIndex) | 从传入的索引处截取,截取到末尾,得到新的字符串返回 |
public String replace(CharSequence target,CharSequence replacement) | 使用新值,讲字符串中的旧值替换,得到新的字符串 |
public boolean containt(CharSequence s) | 判断字符串中是否包含了某个字符串 |
public boolean startsWith(String prefix) | 判断字符串是否以某个字符串内容为开头,是则返回true |
public String[ ] split(String regex) | 把字符串按照某个字符串内容分割,返回字符串数组回来 |
public class StringDemo2 {
public static void main(String[] args) {
//生成验证码
String code =getCode(4);
System.out.println(code);
System.out.println(getCode(6));
}
//帮我生成指定位数的验证码返回,每位可能是大小写字母或者数字
//帮我用String变量记住全部要用到的字符
public static String getCode(int n){
//1、定义一个变量记住所有的字符
String source = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
//2、定义一个变量用于记住验证码的随机字符
String code = "";
//3、循环n次,每次生成一个随机字符,拼接成字符串
for (int i = 0; i < n; i++) {
//4、随机一个索引
int index = (int)(Math.random()*source.length());
//5、根据索引获取字符,拼接成字符串
code += source.charAt(index);
}
//6、返回
return code;
}
}
2、ArrayList
ArrayList代表集合,是一种容器,用来装数据的,类似于数组。
集合相对于数组,容量大小可变,功能丰富,开发中用的更多。
ArrayList是什么?怎么使用?
- 是集合中最常用的一种,ArrayList是泛型类,可以约束存储的数据类型。
- 创建对象:调用无参数构造器public ArrayList( )初始化对象
- 调用增删改查数据的方法
常用方法 | 说明 |
public ArrayList() | 创建一个空的集合对象 |
public boolean add(E e) | 在集合的末尾添加一个指定的元素,并返回true |
public void add(int index,E element) | 在集合的指定索引位置添加一个指定的元素,并返回true |
public E get(int index) | 返回指定索引位置的元素 |
public int size() | 返回集合中元素的个数 |
public E remove(int index) | 删除指定索引位置的元素,并返回被删除的元素 |
public boolean remove(Object o) | 删除指定元素,并返回删除是否成功 |
public E set(int index,E element) | 修改指定索引位置的元素,并返回被修改的元素 |
import java.util.ArrayList;
public class ArrayListDemo1 {
public static void main(String[] args) {
//掌握ArrayList的基本使用
//创建ArrayList对象,代表一个集合容器
ArrayList<String> list = new ArrayList<>();//泛型定义集合
//添加数据
list.add("hello");
list.add("world");
list.add("java");
System.out.println(list);
//查看数据
System.out.println(list.get(0));
System.out.println(list.get(1));
System.out.println(list.get(2));
//遍历集合
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
//删除数据
list.remove(1);//根据索引删除
System.out.println(list);
System.out.println(list.remove("java"));//根据元素删除
System.out.println(list);
//修改数据
list.set(0,"java");
System.out.println(list);
}
}
五、GUI编程
什么是GUI编程?
- GUI,全称Graphical User Interface,是指图形用户界面。
- 通过图形元素(如窗口、按钮、文本框等)与用户进行交互。
- 与命令行界面(CLI)相比,GUI更加直观、友好。
为什么学习GUI编程?
- 增强用户体验
- 广泛应用于桌面应用程序开发
- Java提供了强大的GUI编程支持
Java的GUI编程包
- AWT(Abstract Window Toolkit)
- 提供了一组原生的GUI组件,依赖于操作系统的本地窗口系统
- Swing
- 基于AWT,提供了更丰富的GUI组件,轻量级组件,不依赖于本地窗口系统
常见的Swing组件
- JFrame:窗口
- JPanel:用于组织其他组件的容器
- JButton:按钮组件
- JTextField:输入框
- JTable:表格
- ...
import javax.swing.*;
public class JFrameDemo1 {
public static void main(String[] args){
//快速入门GUI Swing的编程
//1、创建一个窗口,有一个登录按钮
JFrame jf=new JFrame();
JPanel jp=new JPanel();//创建一个面板
jf.add(jp);//将面板添加到窗口
jf.setSize(400,300);//设置窗口大小
jf.setLocationRelativeTo(null);//设置窗口居中
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭窗口退出程序
JButton btn=new JButton("登录");//创建一个按钮
btn.setBounds(100,100,100,50);//设置按钮的位置和宽高
jp.add(btn);//将按钮添加到面板
jf.setVisible(true);//显示窗口
}
}
布局管理器(Layout Manager)它们可以决定组件在容器中的布局方式,避免了手动设置每个组件的位置和大小,从而简化了GUI设计过程。
常见的布局管理器
- FlowLayout:按照水平方向从左到右排列组件,当一行排满时,自动切换到下一行
- 特点:默认居中对齐,可以设置左对齐或右对齐;适用于需要简单排列的场景。
- BorderLayout:将容器分为5个区域,North、South、East、West、Center,每个区域只能添加一个组件。
- 特点:适用于要在特定区域布局组件的场景;中间的组件会自动填充剩余的空间。
- GridLayout:将容器按照指定的行数和列数进行布局,每个组件占一个单元格,所有组件大小相同。
- 特点:适用于需要将组件均分到容器中的场景;行和列的数量可以指定。
- BoxLayout:将容器按照单一水平或垂直方向排列组件,每个组件占一个单元格,所有组件大小相同。
- 特点:适用于需要沿单一方向排列组件的场景;可以添加垂直或水平方向的间隔来调整组件间距。
事件处理:GUI编程中,事件的处理是通过事件监听器(Event Listener)来完成的。
常用的时间监听器对象
- 点击事件监听器 ActionListener
- 按键事件监听器 KeyListener
- 鼠标行为监听器 MouseListener
- ...
事件的几种常见写法
1、直接提供实现类,用于创建事件监听对象。
2、直接使用匿名内部类的对象,代表事件监听对象。
3、自定义窗口,让窗口对象实现事件接口。
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class Test {
public static void main(String[] args)
{
//认识GUI的事件处理机制
//1、创建一个窗口,有一个登录按钮
JFrame jf=new JFrame();
JPanel jp=new JPanel();//创建一个面板
jf.add(jp);//将面板添加到窗口
jf.setSize(400,300);//设置窗口大小
jf.setLocationRelativeTo(null);//设置窗口居中
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置关闭窗口退出程序
JButton btn=new JButton("登录");//创建一个按钮
btn.setBounds(100,100,100,50);//设置按钮的位置和宽高
jp.add(btn);//将按钮添加到面板
//给按钮绑定点击事件监听器对象
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//一旦点击了按钮,底层触发这个方法执行
//e 是事件对象,封装了事件相关信息
JOptionPane.showMessageDialog(jf,"用户点击了登录按钮");
}
});
//需求:监听用户键盘上下左右四个按键的事件:
//给jf窗口整体绑定按键事件
jf.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
//一旦用户按下了键盘上的某个键,底层触发这个方法执行
//e是事件对象,封装了事件相关信息
//获取用户按下的键是哪个
int keyCode=e.getKeyCode();//拿事件源头的键帽编号
//判断用户按下的键是哪个
if(keyCode==KeyEvent.VK_UP){
System.out.println("用户按下了上键");
}else if(keyCode==KeyEvent.VK_DOWN){
System.out.println("用户按下了下键");
}
else if(keyCode==KeyEvent.VK_LEFT){
System.out.println("用户按下了左键");
}
else if(keyCode==KeyEvent.VK_RIGHT){
System.out.println("用户按下了右键");
}
}
});
jf.setVisible(true);//显示窗口
//让窗口成为焦点
jf.requestFocus();
}
}