2012-12-23 84 views
1

我所做的小程序彈跳球,並在課堂上Ball.java我做了內部類TimerListener與方法repaint(),當我運行小程序,而不是重繪球,JAVA連連油漆球(不刪除,然後繪畫)。彈跳球小程序

,這裏是我的類Ball.java

import javax.swing.Timer; 
import java.awt.*; 
import javax.swing.*; 
import java.awt.event.*; 

public class Ball extends JPanel { 
private int delay = 10; 

Timer timer=new Timer(delay, new TimerListener()); 

private int x=0; 
private int y=0; 
private int dx=20; 
private int dy=20; 
private int radius=5; 

private class TimerListener implements ActionListener{ 
    public void actionPerformed(ActionEvent e) { 
     repaint(); 
    } 
} 

public void paintComponent(Graphics g){ 

    g.setColor(Color.red); 
    if(x<radius) dx=Math.abs(dx); 
    if(x>(getWidth()-radius)) dx=-Math.abs(dx); 
    if(y>(getHeight()-radius)) dy=-Math.abs(dy); 
    if(y<radius) dy=Math.abs(dy); 
    x+=dx; 
    y+=dy; 
    g.fillOval(x-radius, y-radius, radius*2, radius*2); 
     } 
public void suspend(){ 
    timer.stop(); 
} 
public void resume(){ 
    timer.start(); 
} 
public void setDelay(int delay){ 
this.delay=delay; 
timer.setDelay(delay); 
} 
} 

這裏是我的BallControl.java

import javax.swing.*; 
import java.awt.event.*; 
import java.awt.*; 
public class BallControl extends JPanel{ 

private Ball ball = new Ball(); 
private JButton jbtSuspend = new JButton("Suspend"); 
private JButton jbtResume = new JButton("Resume"); 
private JScrollBar jsbDelay = new JScrollBar(); 

public BallControl(){ 
    JPanel panel = new JPanel(); 
    panel.add(jbtSuspend); 
    panel.add(jbtResume); 
    //ball.setBorder(new javax.swing.border.LineBorder(Color.red)); 
    jsbDelay.setOrientation(JScrollBar.HORIZONTAL); 
    ball.setDelay(jsbDelay.getMaximum()); 
    setLayout(new BorderLayout()); 
    add(jsbDelay, BorderLayout.NORTH); 
    add(ball, BorderLayout.CENTER); 
    add(panel, BorderLayout.SOUTH); 

    jbtSuspend.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      ball.suspend(); 
     } 
    }); 

    jbtResume.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      ball.resume(); 
     } 
    }); 

    jsbDelay.addAdjustmentListener(new AdjustmentListener() { 
     public void adjustmentValueChanged(AdjustmentEvent e) { 
      ball.setDelay(jsbDelay.getMaximum() - e.getValue()); 
     } 
    }); 

} 
    } 

回答

5

代碼是不應該也改變了球對象的位置的定時碼?換句話說,它不應該改變它的x和y值嗎?即,

private class TimerListener implements ActionListener{ 
    public void actionPerformed(ActionEvent e) { 

     // first change x and y here ***** 

     repaint(); 
    } 
} 

否則,球應該如何移動少得多的反彈?

您似乎在您的paintComponent(...)方法中有此更改位置代碼,這並不好,因爲您無法完全控制何時甚至是否調用此方法。由於這個原因,改變這個對象狀態的程序邏輯和代碼不屬於該方法的範圍。

此外,您的paintComponent(...)方法重寫需要調用超級的第一行paintComponent(...)方法,以便在繪製新球之前可以擦除舊球。

+0

我忘了把'super.paintComponent(g)'放在方法'paintComponent'中.... – Mikky

+0

@ user1906377:是的,我知道這就是爲什麼我建議你這樣做。 –

+0

@ user1906377:但不要嘗試從paintComponent中改變位置,因爲這不是一個好的方法。您無法完全控制paintComponent何時或如何被調用。將更改位置代碼移到您的計時器。 –