为什么写这个项目
- 好玩
- 涉及到java各个方面的技术
1,java面向对象
2,多线程
3,文件i/o操作
4,数据库 - 巩固知识
java绘图坐标体系
坐标体系-介绍
坐标体系-像素
- 计算机在屏幕上显示的内容都是由屏幕上的每一个像素组成的
- 像素是一个密度单位,而厘米是长度单位,两者无法比较
例如“计算机显示器的分辨率是800*600,表示计算机屏幕上的每一行由800个点组成,共有600行。整个计算机屏幕共有480000个像素。
介绍-快速入门
入门案例-在面板上绘制一个圆
public class DrawCircle extends JFrame {//JFrame 对应窗口,可以理解成一个画框
public static void main(String[] args) {
new DrawCircle();
}
//1,定义一个面板
private MyPanel mp = null;
public DrawCircle() {//构造器
//2,初始化面板
mp = new MyPanel();
//3,把面板放入到画框
this.add(mp);
//4,设置窗口的大小
this.setSize(800, 800);
//5,(默认退出)当点击窗口的小×,程序完全退出
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//6,可以显示
this.setVisible(true);
}
}
//1,先定义一个MyPanel类,继承JPanel类, 画图形,在画板上画
class MyPanel extends JPanel {
/*
1,MyPanel 对象就是一个画板
2,Graphics g 可以把g理解成一支画笔
3,Graphics 提供了很多绘图方法
*/
//paint方法被调用:当组件第一次在屏幕显示时,程序会自动调用paint()方法来绘制组件
@Override
public void paint(Graphics g) {//绘图方法
super.paint(g);//调用父类的方法完成初始化
System.out.println("paint方法被调用了~");
//画一个圆形 drawOval(x1,y1,y2,y2)
// g.drawOval(0,0,100,100);
//画直线 drawLine(int x1,int y1,int x2,int y2)
// g.drawLine(10, 10, 100, 100);
//画矩形边框 drawRect(int x, int y, int width, int height)
//g.drawRect(10, 10, 100, 100);
//画椭圆边框 drawOval(int x, int y, int width, int height)
//填充矩形 fillRect(int x, int y, int width, int height)
//填充椭圆 fillOval(int x, int y, int width, int height)
//设置画笔的颜色
// g.setColor(Color.blue);
// g.drawOval(0,0,100,100);
//画图片 drawImage(Image img, int x, int y, ..)
//1,获取图片资源 /表示在该项目的根目录去获取 图片资源
// Image image = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/01.jpg"));
// g.drawImage(image,10,10,740,500,this);
//画字符串 drawString(String str, int x, int y)//写字
//给画笔设置颜色和字体
g.setColor(Color.red);
//public abstract void setFont(Font font); 调用setFont方法,需要传入一个对象
g.setFont(new Font("隶书", Font.BOLD, 50));//Font.BOLD 表示粗体
//给画笔设置内容
//这里设置的 100, 100, 是 "北京你好"左下角
g.drawString("北京你好", 100, 100);
//设置画笔的字体 setFont(Font font)
//设置画笔的颜色 setColor(Color c)
}
}
绘图原理
- Component类提供了两个和绘图相关最重要的方法
1,paint(Graphics g) 绘制组件的外观
2,repaint() 刷新组件的外观 - 当组件第一次在屏幕显示时,程序会自动调用paint()方法来绘制组件
- 在以下情况下paint() 将会被调用
1,窗口最小化,再最大化
2,窗口的大小发生变化
3,repaint方法被调用
Graphics 类
Graphics类可以理解为:就是画笔。为我们提供了各种绘制图形的方法
绘出坦克
- 坦克父类 Tank
定义坦克的横坐标和纵坐标,进行初始化,并调用set get方法,以供其他类来使用 - 自己的坦克类,继承坦克父类 Hero
重写父类的构造器 - 画板类 MyPanel 继承Jpanel类
1,定义自己的坦克,并初始化自己的坦克
2,重写Jpanel类中的paint方法(传入画笔)
3,通过画笔填充一个矩形区域 g.fillRect();
4,创建drawTank方法,设置参数(int x, int y, Graphics g, int direct, int type) direct:用与控制方向 type:用于控制颜色
5,在paint方法中调用drawTank方法 - 窗体类 TankGame01
1,创建画板对象,并进行初始化
2,把画板传入窗体
3,设置窗体大小
4,设置窗体默认退出
5,设置窗体可见
坦克父类
//坦克父类
public class Tank {
private int x;//坦克的横坐标
private int y;//坦克的纵坐标
public Tank(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
自己的坦克
//自己的坦克,继承坦克父类
public class Hero extends Tank{
//重写父类的构造器
public Hero(int x, int y) {
super(x, y);
}
}
画板类
//画板类
public class MyPanel extends JPanel {
// 1,定义自己的坦克,并初始化自己的坦克
Hero hero = null;
public MyPanel() {//初始化自己的坦克
hero = new Hero(100,100);
}
//2,重写Jpanel类中的paint方法(传入画笔)
@Override
public void paint(Graphics g) {
super.paint(g);
// 3,通过画笔填充一个矩形区域 g.fillRect();
g.fillRect(0,0,1000,750);//填充矩形,默认为黑色
// 5,在paint方法中调用drawTank方法
drawTank(hero.getX(),hero.getY(),g,0,1);
drawTank(hero.getX() +100,hero.getY(),g,0,0);
}
/*
int x 坦克的横坐标
int y 坦克的纵坐标
Graphics g 画笔
int direct 坦克的方向
int type 坦克的类型
*/
//4,创建drawTank方法,设置参数(int x, int y, Graphics g, int direct, int type) direct:用与控制方向 type:用于控制颜色
public void drawTank(int x, int y, Graphics g, int direct, int type){
//根据不同类型的坦克,设置不同的颜色
switch(type){
case 0://我们的坦克
g.setColor(Color.cyan);
break;
case 1://敌人的坦克
g.setColor(Color.yellow);
break;
}
//根据坦克的方向,来绘制坦克
switch (direct){
case 0://表示向上
g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
g.drawLine(x + 20, y + 30, x + 20, y);//画出炮筒
break;
default:
System.out.println("暂时没有处理");
}
}
}
窗体类
//窗体类
public class TankGame01 extends JFrame {//窗体
public static void main(String[] args) {
new TankGame01();
}
private MyPanel mp = null;//1,创建画板对象
public TankGame01(){
mp = new MyPanel();//画板初试化
this.add(mp);//2,把画板传入窗体
this.setSize(1000,750);//3,设置窗体大小
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//4,设置窗体默认退出
this.setVisible(true);// 5,设置窗体可见
}
}
java事件处机制
事件处理机制入门案例:小球移动代码
小球案例中的事件源、事件/对象和事件监听者分别是什么
- 事件源:键盘
- 事件:按下鼠标
- 事件监听者:MyPanel_类(实现KeyListener键盘监听器接口)
public class BallMove extends JFrame{//窗体
public static void main(String[] args) {
BallMove ballMove = new BallMove();
}
//创建画板对象
private MyPanel_ mp = null;
public BallMove() {
mp = new MyPanel_();//初始化画板
this.add(mp);//给窗体添加组件-画板
this.setSize(500,500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//窗体JFrame对象可以监听键盘事件,面板时间了键盘监听器
// 即可以监听到面板发生的监听事件
this.addKeyListener(mp);
this.setVisible(true);
}
}
class MyPanel_ extends JPanel implements KeyListener {//画板 实现键盘监听器
int x = 10;
int y = 10;
@Override
public void paint(Graphics g) {
super.paint(g);
g.fillOval(x,y,10,10);
}
//有字符输出时,该方法就会触发
@Override
public void keyTyped(KeyEvent e) {
}
//当某个键按下,该方法会触发
@Override
public void keyPressed(KeyEvent e) {
// System.out.println("按键");
if (e.getKeyCode() == KeyEvent.VK_DOWN){
y++;
} else if (e.getKeyCode() == KeyEvent.VK_UP) {
y--;
} else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
x--;
} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
x++;
}
//重绘
repaint();
}
//当某个键释放(松开),该方法会触发
@Override
public void keyReleased(KeyEvent e) {
}
}
java事件处理是采取“委派事件模型”。当事件发生时,产生事件的对象,会把此“信息”传递给“事件的监听者”处理,。这里所说的“信息”实际上是java.awt.event事件类库里某个类所创建的对象,把他成为“事件的对象”
让坦克动起来
在前面绘制好坦克的基础上实现改变方向和移动
改变坦克的方向
- 坦克父类 Tank
定义坦克方向的属性,进行初试化,并创建set get方法 - 自己的坦克类,继承坦克父类 Hero
不变 - 画板类 MyPanel 继承Jpanel 实现 KeyListener 键盘监听器接口
1,在drawTank方法中,设置方向:向上 向下 向左 向右
2,在实现KeyListener 键盘监听器接口时,重写接口中的方法
3,在keyPressed方法中,将键盘输入与方向相结合
4,在keyPressed中调用repaint方法进重绘,使的画出的图形改变时,仍然可以画出 - 窗体类 TankGame02
让窗体监听画板发生的监事件
使坦克动移动起来
- 坦克父类 Tank
1,定义 可以上下左右移动的方法。使得在MyPanel 类中可以直接调用方法进行移动
2,定义speed属性,进行初始化,并添加set get方法 - 自己的坦克类,继承坦克父类 Hero
不变 - 画板类 MyPanel 继承Jpanel 实现 KeyListener 键盘监听器接口
1,在MyPanel 类中调用setSpeed设置speed的大小
3,在keyPressed方法中,调用hero中的 上下左右方法 - 窗体类 TankGame02
不变
坦克父类
//坦克父类
public class Tank {
private int x;//坦克的横坐标
private int y;//坦克的纵坐标
private int direct;//坦克方向 //direct表示方法: 0:向上 1:向右 2:向下 3:向左
private int speed = 1;
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
//定义 可以上下左右移动的方法
public void moveUp() {
y -= speed;
}
public void moveDown() {
y += speed;
}
public void moveLeft() {
x -= speed;
}
public void moveRight() {
x += speed;
}
public Tank(int direct) {
this.direct = direct;
}
public int getDirect() {
return direct;
}
public void setDirect(int direct) {
this.direct = direct;
}
public Tank(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
自己的坦克,继承坦克父类
//自己的坦克,继承坦克父类
public class Hero extends Tank {
public Hero(int x, int y) {
super(x, y);
}
}
画板类
//画板类
public class MyPanel extends JPanel implements KeyListener {
//定义我的坦克
Hero hero = null;
public MyPanel() {//初始化自己的坦克
hero = new Hero(100,100);
hero.setSpeed(5);
}
@Override
public void paint(Graphics g) {
super.paint(g);
//3,通过画笔填充一个矩形区域 g.fillRect();
g.fillRect(0,0,1000,750);//填充矩形,默认为黑色
drawTank(hero.getX(),hero.getY(),g,hero.getDirect(),1);
// drawTank(hero.getX() +100,hero.getY(),g,hero.getDirect(),0);
// drawTank(hero.getX() +200,hero.getY(),g,hero.getDirect(),0);
// drawTank(hero.getX() +300,hero.getY(),g,hero.getDirect(),1);
}
/*
int x 坦克的横坐标
int y 坦克的纵坐标
Graphics g 画笔
int direct 坦克的方向
int type 坦克的类型
*/
public void drawTank(int x, int y, Graphics g, int direct, int type){
//根据不同类型的坦克,设置不同的颜色
switch(type){
case 0://敌人的坦克
g.setColor(Color.cyan);
break;
case 1://我的坦克
g.setColor(Color.yellow);
break;
}
//根据坦克的方向,来绘制坦克
//direct表示方法: 0:向上 1:向右 2:向下 3:向左
switch (direct){
case 0://表示向上
g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
g.drawLine(x + 20, y + 30, x + 20, y);//画出炮筒
break;
case 1://表示向右
g.fill3DRect(x, y, 60, 10, false);//画出坦克上边轮子
g.fill3DRect(x, y+30, 60, 10, false);//画出坦克下边轮子
g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克盖子
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子
g.drawLine(x + 30, y + 20, x + 60, y+20);//画出炮筒
break;
case 2://表示向下
g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子
g.drawLine(x + 20, y + 30, x + 20, y+60);//画出炮筒
break;
case 3://表示向左
g.fill3DRect(x, y, 60, 10, false);//画出坦克上边轮子
g.fill3DRect(x, y+30, 60, 10, false);//画出坦克下边轮子
g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克盖子
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子
g.drawLine(x + 30, y + 20, x , y+20);//画出炮筒
break;
default:
System.out.println("暂时没有处理");
}
}
//有字符输出时,该方法就会触发
@Override
public void keyTyped(KeyEvent e) {
}
//当某个键按下,该方法会触发
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_W){
//改变坦克方向
hero.setDirect(0);
//让坦克动起来
hero.moveUp();
} else if (e.getKeyCode() == KeyEvent.VK_S) {
hero.setDirect(2);
hero.moveDown();
} else if (e.getKeyCode() == KeyEvent.VK_A) {
hero.setDirect(3);
hero.moveLeft();
} else if (e.getKeyCode() == KeyEvent.VK_D) {
hero.setDirect(1);
hero.moveRight();
}
//重绘
repaint();
}
//当某个键释放(松开),该方法会触发
@Override
public void keyReleased(KeyEvent e) {
}
}
窗体类
//窗体类
public class TankGame02 extends JFrame {//窗体
public static void main(String[] args) {
new TankGame02();
}
private MyPanel mp = null;//创建画板对象
public TankGame02(){
mp = new MyPanel();//画板初试化
this.add(mp);//把画板传入窗体
this.setSize(1000,750);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//窗体JFrame对象可以监听键盘事件,面板实现了键盘监听器
// 即可以监听到面板发生的监听事件
this.addKeyListener(mp);
this.setVisible(true);
}
}