為什么寫這個項目
- 好玩
- 涉及到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);}}