为什么写这个项目
- 好玩
- 涉及到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()方法来绘制组件@Overridepublic 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方法(传入画笔)@Overridepublic 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;@Overridepublic void paint(Graphics g) {super.paint(g);g.fillOval(x,y,10,10);}//有字符输出时,该方法就会触发@Overridepublic void keyTyped(KeyEvent e) {}//当某个键按下,该方法会触发@Overridepublic 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();}//当某个键释放(松开),该方法会触发@Overridepublic 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);}@Overridepublic 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("暂时没有处理");}}//有字符输出时,该方法就会触发@Overridepublic void keyTyped(KeyEvent e) {}//当某个键按下,该方法会触发@Overridepublic 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();}//当某个键释放(松开),该方法会触发@Overridepublic 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);}}