carlbron
carlbron

Reputation: 3

Timer increasing speed every time I click a button

I want to execute an animation in an applet every time I click a button. The first time I click the button everything works fine. But the second time, the speed of the animation increases. The third time the speed of the animation increases a little bit more, and the fourth, and the fifth,...

I don´t know what is happening with the timer. How can i fix it?

In the applet I use this code:

JButton btnIniciar = new JButton("Iniciar");
    btnIniciar.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {     
            Timer timer = new Timer(50, new ActionListener(){
                public void actionPerformed(ActionEvent e) {
                    //I have a list of packages to animate
                    for (Package p: listaPaquetes){
                        p.animate();
                        panel.repaint();
                    }                             
                }
            });

            timer.start();
        }

And this is the code of repaint in the panel:

protected void paintComponent(Graphics g) {
    super.paintComponent(g);     
    //I use the same list of the applet   
    for (Package p: listaPaquetes){
        //Paint the package
        p.paintPackage(g);
    }

}

This is how it works, the animation sends packages from left to right

Upvotes: 0

Views: 490

Answers (1)

stjepano
stjepano

Reputation: 1152

When you press the button you are creating new javax.swing.Timer and invoking timer.start() which in this case is scheduled to run 50ms after the button press and repeat each 50ms.

When you press the button second time, you create and start another timer (a new one) which again works each 50ms with 50ms initial delay. You are now essentially doubling the number of repaint calls.

With third press you are tripling the number of repaint calls because you have 3 timers running.

If your button presses were timed properly it will look as if the speed has tripled (with 3 button presses).

If you do not want this behavior you can prevent the timer to run if it is already running like this:

private Timer timer = null;

// ...

JButton btnIniciar = new JButton("Iniciar");
btnIniciar.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent arg0) { 
        // prevent the timer from running again if it is already running
        if ( timer != null && timer.isRunning() ) return;

        timer = new Timer(50, new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                //I have a list of packages to animate
                for (Package p: listaPaquetes){
                    p.animate();
                    panel.repaint();
                }                             
            }
        });

        timer.start();
    }

Please note that you need to make timer into an instance variable. Also you can replace the line:

if ( timer != null && timer.isRunning() ) return;

with

if ( timer != null ) return;

I simply wanted to show you that Timer has isRunning() method.

You can also stop the timer by invoking timer.stop() method.

Upvotes: 2

Related Questions