目录
五. 事件
涉及知识:事件,监听,接口,匿名内部类,多态 ,object父类
-
事件(Event): 在Java中,事件是指程序执行过程中发生的某个特定的动作或状态变化。例如,用户点击按钮、鼠标移动、键盘按下等都可以视为事件。Java提供了事件驱动的编程模型,通过注册事件监听器,可以在特定事件发生时执行相应的操作。
-
监听(Listener): 监听是指在特定事件发生时,执行相应操作的机制。在Java中,监听器(Listener)是一种实现了特定接口的类,用于接收并处理特定类型的事件。当事件发生时,通过触发监听器的方法,可以执行事先定义好的操作。
-
接口(Interface): 接口是Java中的一种抽象类型,它定义了一组方法的规范,但没有提供具体的实现。接口可以被类实现(implements),通过实现接口中定义的方法,来达到接口规范的要求。接口的作用在于实现类与使用类之间的解耦,提供了一种约定,使得不同的类可以按照同样的方式进行交互。
-
匿名内部类(Anonymous Inner Class): 匿名内部类是Java中的一种特殊的内部类,它没有显式的类名。匿名内部类通常用于临时需要实现某个接口或继承某个类的情况,可以在创建对象的同时直接实现接口或继承类,并覆盖其方法。匿名内部类的语法较简洁,可以在一行代码中完成对象的创建和方法的实现。
-
多态(Polymorphism): 多态是Java面向对象编程的一个重要概念,它允许不同类型的对象对同一个消息做出不同的响应。多态性是通过继承和接口实现实现的,当一个类实现了某个接口或继承了某个父类,并覆盖了相应的方法时,可以通过父类或接口类型的引用来引用具体的子类对象,并根据具体的对象类型调用相应的方法。
-
Object父类: Object是Java中所有类的父类,它定义了一些通用的方法,如equals()、hashCode()、toString()等。所有Java类默认都继承了Object类,可以通过在类中重写这些方法来实现自定义的行为。Object类的存在使得在不确定对象类型的情况下,仍可以使用通用的方法对对象进行操作。
基础的动态监听
方法1.在实际的开发中,每个按钮的业务逻辑不同,当一个接口的实现类只被用到一次的时候哪这个类就没有必有单独创建一个类,可以用一个匿名内部类
方法2.用本界面去implements Actionlistener,把重写的方法写在自己的类中,在传递的时候,使用this,表示本类的对象
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class MyJFrame extends JFrame implements ActionListener {
//创建一个按钮对象
JButton jtb1 = new JButton("点我呀");
//创建一个按钮对象
JButton jtb2 = new JButton("点我呀");
public MyJFrame(){
//设置界面的宽高
this.setSize(603,680);
//设置界面的标题
this.setTitle("拼图单机版 v1.0");
//设置界面置顶
this.setAlwaysOnTop(true);
//设置界面居中
this.setLocationRelativeTo(null);
//设置关闭模式
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//取消默认的剧中放置,只有取消了才会按照XY轴的方式添加组件
this.setLayout(null);
//设置位置和宽高
jtb1.setBounds(0,0,100,50);
//给按钮添加事件
jtb1.addActionListener(this);//本类的对象
//设置位置和宽高
jtb2.setBounds(100,0,100,50);
jtb2.addActionListener(this);
//把按钮添加到整个界面当中
this.getContentPane().add(jtb1);
this.getContentPane().add(jtb2);
//让整个界面显示出来
this.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
//对当前的按钮进行判断
//获取当前被操作的那个按钮对象
Object source = e.getSource();
if(source == jtb1){
jtb1.setSize(200,200);
}
else if(source == jtb2){
Random r = new Random();
jtb2.setLocation(r.nextInt(500),r.nextInt(500));
}
}
}
结果演示:点击按钮
鼠标监听机制-MouseListener
k
import javax.swing.*; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; public class MyJFrame2 extends JFrame implements MouseListener { //创建一个按钮对象 JButton jtb1 = new JButton("点我呀"); public MyJFrame2() { //设置界面的宽高 this.setSize(603, 680); //设置界面的标题 this.setTitle("拼图单机版 v1.0"); //设置界面置顶 this.setAlwaysOnTop(true); //设置界面居中 this.setLocationRelativeTo(null); //设置关闭模式 this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //取消默认的剧中放置,只有取消了才会按照XY轴的方式添加组件 this.setLayout(null); //设置位置和宽高 jtb1.setBounds(0, 0, 100, 50); //给按钮绑定鼠标事件 jtb1.addMouseListener(this); //把按钮添加到整个界面当中 this.getContentPane().add(jtb1); //显示 this.setVisible(true); } @Override public void mouseClicked(MouseEvent e) { System.out.println("单击"); } @Override public void mousePressed(MouseEvent e) { System.out.println("按下不松"); } @Override public void mouseReleased(MouseEvent e) { System.out.println("松开"); } @Override public void mouseEntered(MouseEvent e) { System.out.println("划入"); } @Override public void mouseExited(MouseEvent e) { System.out.println("划出"); } }
键盘监听
细节1: 如果我们按下一个按键没有松开,那么会重复的出调用KeyPressed方法
细节2: 每一个按键都有一个对应的编号,以其区分不同的按键
六. 美化界面
当代码写的越来越多,要再接他添加一个需求,要分析清楚新的代码到底写在哪里
在初始化图片的类中添加
调整位置需要反复尝试找到合适的位置
1.重新调整小图片的位置
//指定图片位置 jLabel.setBounds(105 * j + 83, 105 * i + 134, 105, 105);
2. 添加背景图片并调整位置
细节: 先加载图片在上方,后加载的图片在下方
所以添加背景图片的代码写在添加小图片外
//添加背景图片 JLabel background = new JLabel(new ImageIcon("E:\\Ideal Code Exercise\\puzzllegame\\image\\background.png")); background.setBounds(40,40,508,560); //把背景图片添加到界面当中 this.getContentPane().add(background);
3.为每一张小图片添加边框
写在添加小图片的循环体内,在添加小图片的路径下
//给图片加边框 jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED));
//0 : 表示让图片凸起来
//1 :表示让图片凹下去
选中BevelBorder( ctrl + b)
4.优化路径
绝对路径 : 从盘符开始
相对路径: 非盘符开始(相对于当前项目而言,在当前项目下去找XX文件)
JLabel background = new JLabel(new ImageIcon("E:\\Ideal Code Exercise\\puzzllegame\\image\\background.png")); 路径可优化为: 注意:项目名要去掉 或者加上“..//” JLabel background = new JLabel(new ImageIcon("image\\background.png")); JLabel background = new JLabel(new ImageIcon("..\\puzzllegame\\image\\background.png"));
结果展示:
七. 移动图片
上移动 : 把空白方块下方的图片向上移
每张小图片实际上都是与一个数字相对应,这些数字都是存放在二维数组当中,
找到0 和 1 - 15 某个数字进行交换,将0在数组中的索引与它下面图片交换,交换完后再添加相应的图片
1.先实现KeyListtener接口 ,给整个游戏界面添加一个键盘监听事件
public class GameJFrame extends JFrame implements KeyListener
2.统计一下空白方块的位置
3.在keyReleased方法中实现逻辑
4.Bug修复(数组越界)进行一个判断,“触底”直接return结束方法
@Override
public void keyReleased(KeyEvent e) {
//对上 下 左 右进行判断
//左:37 上:38 右: 39 下: 40
int code = e.getKeyCode();
if(code == 37){
System.out.println("向左移动");
if(y == 3) {
return;
}
//逻辑
//把空白方块右方的数字往左移
//x , y 表示空白方块
//x , y - 1表示空白方块右方的数字
data[x][y] = data[x][y + 1];
data[x][y + 1] = 0;
y++;
//调用方法按照最新的数字加载图片
initImage();
} else if (code == 38) {
System.out.println("向上移动");
if(x == 3) {
//表示空白方块已经在最下方了,它下面没有图片了
return;
}
//逻辑
//把空白方块下方的数字往上移
//x , y 表示空白方块
//x + 1 , y 表示空白方块下方的数字
//把空白方块下方的数字赋值给空白方块
data[x][y] = data[x + 1][y];
data[x + 1][y] = 0;
x++;
//调用方法按照最新的数字加载图片
initImage();
} else if (code == 39) {
System.out.println("向右移动");
if(y == 0) {
return;
}
//逻辑
//把空白方块左方的数字往右移
//x , y 表示空白方块
//x , y + 1 表示空白方块左方的数字
//把空白方块下方的数字赋值给空白方块
data[x][y] = data[x][y - 1];
data[x][y - 1] = 0;
y--;
//调用方法按照最新的数字加载图片
initImage();
} else if (code == 40) {
System.out.println("向上移动");
if(x == 0) {
return;
}
//逻辑
//把空白方块下方的数字往上移
//x , y 表示空白方块
//x - 1, y 表示空白方块上方的数字
//把空白方块下方的数字赋值给空白方块
data[x][y] = data[x - 1][y];
data[x - 1][y] = 0;
x--;
//调用方法按照最新的数字加载图片
initImage();
}
}