【问题标题】:Bouncing Ball applet弹跳球小程序
【发布时间】:2012-12-23 11:57:00
【问题描述】:

我制作了小程序 Bouncing Ball 并在类 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());
        }
    });

}
    }

【问题讨论】:

    标签: java swing animation


    【解决方案1】:

    Timer 不应该也改变 Ball 对象的位置吗?换句话说,它不应该改变它的 x 和 y 值吗?即,

    private class TimerListener implements ActionListener{
        public void actionPerformed(ActionEvent e) {
    
            // first change x and y here *****
    
            repaint();
        }
    }
    

    否则,球应该如何移动少得多反弹?

    您的paintComponent(...) 方法中似乎有此更改位置代码,这并不好,因为您无法完全控制何时甚至是否调用此方法。因此,更改此对象状态的程序逻辑和代码不属于该方法。

    此外,您的 paintComponent(...) 方法覆盖需要在其第一行调用 super 的 paintComponent(...) 方法,以便在绘制新球之前可以擦除旧球。

    【讨论】:

    • @user1906377:是的,我知道这就是我建议你这样做的原因。
    • @user1906377:但不要尝试从paintComponent 中更改位置,因为这不是一个好方法。您无法完全控制何时或是否调用paintComponent。将更改位置代码移动到您的计时器。
    • @user1906377 另见related example
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-20
    • 1970-01-01
    • 2013-05-23
    • 1970-01-01
    • 2012-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多