Java--彈彈球(定時器與圖形動畫設計)
阿新 • • 發佈:2019-01-09
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.Timer;
import javax.swing.colorchooser.ColorSelectionModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class ballsJFrame extends JFrame implements ChangeListener{
private JSpinner spinner;//微調按鈕
private ballsCanvas canvas;//用畫布畫球
public ballsJFrame() {
super("彈彈球");
setBounds(300, 200, 400, 300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
Color colors[]={Color.red ,Color.yellow ,Color.BLUE,Color.green,Color.gray};//小球顏色及個數
canvas=new ballsCanvas(colors, 100 );//new一個畫布
getContentPane().add(canvas);
JPanel panel=new JPanel();
getContentPane().add(panel,BorderLayout.SOUTH);//getContentPane().add(panel,"SOUTH");
panel.add(new JLabel("dalay"));
spinner =new JSpinner();//new一個微調按鈕
spinner.setValue(100);//設定初始值new ballsCanvas(colors, 100);
panel.add(spinner);
spinner.addChangeListener(this);//監聽裡面的數值發生變化
setVisible(true);
}
public static void main(String[] args) {
new ballsJFrame();
}
public void stateChanged(ChangeEvent e) {
int delay=Integer.parseInt(""+spinner.getValue());//獲取微調按鈕文本里的值
canvas.setDelay(delay);//對timer設定數值
}
}
class ballsCanvas extends Canvas implements ActionListener, FocusListener{
private ball balls[];//球
private Timer timer;//定時器
class ball{//內部類,,底下畫球時就可以直接呼叫座標,不用getX()函式
private int x,y;
private Color color;
boolean up,left;//初始值是false
public ball(int x, int y, Color color) {
this.x = x;
this.y = y;
this.color = color;
}
}
public ballsCanvas(Color[] colors,int delay) {
this.balls = new ball[colors.length];
for(int i=0,x=40;i<colors.length;i++,x+=40){
balls[i]=new ball(x,x,colors[i]);
}
this.addFocusListener(this);//監聽焦點
timer=new Timer(delay,this);//用法和btn.addActionLis一樣
timer.start();//定時器本身是一個執行緒物件,必須要啟動才會生效
}
public void setDelay(int delay){//在ballsJFrame 類中的方法進行設定數值
timer.setDelay(delay);
}
public void paint(Graphics g) {//畫筆
for(int i=0;i<balls.length;i++){
g.setColor(balls[i].color);//用當前顏色畫球
//方法1:
balls[i].x=balls[i].left? balls[i].x-5 : balls[i].x+5 ;
//遇到邊界就改變方向
if(balls[i].x<=0 || balls[i].x+20>=this.getWidth()){//balls[i].x+20和balls[i].y+20因為球的座標是 **球外接正方形左上方的那一點**,所以判斷球碰到下面和右邊的邊界時要加上求的直徑g.fillOval(balls[i].x, balls[i].y, 20, 20);
balls[i].left=!balls[i].left;
}
balls[i].y=balls[i].up? balls[i].y-5 : balls[i].y+5 ;
if(balls[i].y<=0 || balls[i].y+20>=this.getHeight()){
balls[i].up=!balls[i].up;
}
//方法2:
// balls[i].x+=5;//球被畫死了
// balls[i].y+=5;
g.fillOval(balls[i].x, balls[i].y, 20, 20);//畫實心球,直徑20,20
}
}
public void actionPerformed(ActionEvent e) {?//監聽執行緒,每delay時間間隔畫一次球
repaint();
}
public void focusGained(FocusEvent e) {//監聽焦點,點選畫布時停止
timer.stop();
}
public void focusLost(FocusEvent e) {//監聽焦點,點選其他重新啟動,如微調按鈕編輯框
timer.restart();
}
}
結果顯示: