2014-03-13 480 views
1

可以使用你的幫助作業,包括擺動定時器,動作監聽器和多個對象。我不知道是否張貼的問題在這裏允許的,但我在使用動畫麻煩,這裏是我迄今爲止Java定時器動作監聽器

創建一個具有兩個雙域x和y一類顆粒, 構造將這些字段初始化爲0 和500之間的隨機值,返回它們的值的方法getX和getY以及隨機將x和y的值 中的值加1或減1的方法void move()。 (添加到x和y的數量是兩個單獨的隨機數 。)接下來,創建一個類ParticleFieldWithTimer,它擴展了 JPanel。這個類應該更喜歡500 * 500像素的大小。它的 構造函數應該首先用100個粒子對象填充一個ArrayList字段,然後啓動一個Swing Timer,該Swing Timer的滴答時間爲 秒的25倍。在每次打勾時,動作偵聽器應首先爲每個粒子調用方法 移動,然後調用重繪。 ParticleFieldWithTimer的paintComponent 方法應將每個粒子繪製爲其當前座標的3 * 3 矩形。確保定時器將當用戶關閉框架

這是ParticleFieldWithTimer類

import java.awt.Dimension; 
import java.awt.FlowLayout; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.util.ArrayList; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 


public class ParticleFieldWithTimer extends JPanel{ 
    private ArrayList<Particle> particle = new ArrayList<Particle>(); 
    Timer timer; 
    boolean b; 
    public ParticleFieldWithTimer(){ 
     this.setPreferredSize(new Dimension(500,500)); 


    for(int i = 0; i < 100; i++) { 
     particle.add(new Particle()); 
     timer = new Timer(40, new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       // change polygon data 
       // ... 
       Particle p = new Particle(); 
       p.move(); 
       repaint(); 

      } 
     }); 


    } 





} 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D)g; 
     for (Particle p: particle) { 

     double temp1 = p.getX(); 
     double temp2 = p.getX(); 
     int tempX = (int) temp1; 
     int tempY = (int) temp2; 
     g2.fillRect(tempX, tempY, 3, 3); 
     } 




    } 
    public static void main(String[] args) { 
     final JFrame f = new JFrame("ParticleField"); 
     final ParticleFieldWithTimer bb = new ParticleFieldWithTimer(); 
     f.setLayout(new FlowLayout()); 
     f.add(bb); 
     f.addWindowListener(new WindowAdapter() { 
      public void windowClosing(WindowEvent we) { 
       try { 
        bb.finalize(); 
       } catch (Throwable e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
       f.dispose(); 
      } 
     }); 
     f.pack(); 
     f.setVisible(true); 
    } 
} 

這是粒子類

import java.util.Random; 


public class Particle { 
private double x , y ; 

Random r = new Random(); 
public Particle() { 

    x = r.nextDouble()*500; 
    y = r.nextDouble()*500; 

} 
public Double getX() { 
    return x; 
} 
public Double getY() { 
    return y; 
} 
public void move() { 

    x = r.nextInt(2) - 1; 
    y = r.nextInt(2) - 1; 
    System.out.println(x + " " + y); 
} 

}

+0

*「我不知道是否發佈問題..」* DYM作業規範?你的問題是什麼? –

回答

4

這 停止...

for(int i = 0; i < 100; i++) { 
    particle.add(new Particle()); 
    timer = new Timer(40, new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent ae) { 
      // change polygon data 
      // ... 
      Particle p = new Particle(); 
      p.move(); 
      repaint(); 

     } 
    }); 
} 

是錯誤的方法,它會創建一個100 Timer s,這會影響系統的性能。

您還創建計時器滴答新Particle每一次,這是不是你真正想做的事情要麼,你要影響你已經創建了Particle小號...

相反,創建粒子...

for(int i = 0; i < 100; i++) { 
    particle.add(new Particle()); 
} 

然後創建Timer並在其中,通過你已經創建粒子迭代...

timer = new Timer(40, new ActionListener() { 
    @Override 
    public void actionPerformed(ActionEvent ae) { 
     for (Particle p : particle) { 
      p.move(); 
     } 
     repaint(); 
    } 
}); 

不要忘了啓動定時器...

timer.start(); 

或改變Graphics背景下,這可能是仍設置爲面板的背景顏色...

Graphics2D g2 = (Graphics2D) g; 
g2.setColor(Color.RED); 
for (Particle p : particle) { 

我也注意到...

x = r.nextInt(2) - 1; 
y = r.nextInt(2) - 1; 

是不是在做你想做的。它將始終使值在-1和1之間。相反,您想要將結果添加到x/y值中。

x += r.nextInt(2) - 1; 
y += r.nextInt(2) - 1; 

現在,這種由值 「拖」 對面的(主要)統一的方式在屏幕的...

你可以嘗試使用...

x += r.nextBoolean() ? 1 : - 1; 
y += r.nextBoolean() ? 1 : - 1; 

但這最終導致他們在原地跳舞(主要是)...

+0

嗨,謝謝你的回覆。不應該重繪在for循環中,我應該對paintcomponent進行哪些修改? – user3363135

+0

不,你想更新整個模型,然後做一個'repaint'。它實際上不會產生很大的差異,因爲「RepaintManager」可以將重複調用重新組合爲「repaint」成爲單個繪畫事件,但爲什麼要冒這個風險。一步更新模型,更新下一個視圖。因爲'actionPerformed'在EDT的上下文中執行,調用'repaint'只有在'actionPerformed'方法退出之後纔會起作用(在存在'actionPerformed'之前不能調用'paintComponent') – MadProgrammer

+0

謝謝解釋,這很有道理。然而,我的程序似乎仍然有些問題,在paintcomponent我猜我不應該有一個for循環,但我很困惑,我該怎麼辦 – user3363135