0

I am trying to get a simple fast forward button to work. My understanding is initializing a timer as such

timer = new Timer(setspeed, listener);

sets the delay between timer events to the int setspeed in milliseconds.

i have a fast forward button that has the following code:

    public void doFastForward()
    {
        speedcounter++;
        setspeed = speed / speedcounter;
        System.out.print(speedcounter + " " + setspeed + ". "); //checker
        timer.stop();
        timer.setDelay((setspeed));
        timer.start();
        System.out.print(timer.getDelay() + ".. "); //checker 
    }

which is supposed to cut the speed by half, third, fourth, etc, with every button press. Issue is its totally not doing that with my simulation. Is there something I'm missing here?

Terryn
  • 17
  • 5
  • 1
    What's it doing instead? We need more information. You have `System.out` statements: what are they printing? How are you declaring/initializing `speedcounter`, `speed`, etc? – DannyMo May 31 '13 at 18:56
  • Those system outs are just to check the values of the speed counter, which is being printed as a correct value. Speed is a static int declared in the class, and speed counter is a modifier used to change the ACTUAL speed (this being setspeed) of the timer. Everything about the timer is running fine but this. I am simply trying to change how quickly/slowly the events are triggering, and everything I have read has said use timer.setDelay(DesiredTime); to do so, but apparently I'm missing something. – Terryn May 31 '13 at 20:11
  • As a comment of what it is doing, basically nothing. I've timed the event, and it takes as long with or without hitting the "Fast Forward" button – Terryn May 31 '13 at 20:50

1 Answers1

0

timer.setDelay() works for me. Here's a quick example that moves a red square across the screen. Pressing the fast-forward button makes it move faster by calling setDelay on the timer (you'll notice the logic in my ActionListener is identical to yours, albeit different variable names):

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TimerTest extends JFrame {
  public static void main(String[] args) { new TimerTest().setVisible(true); }

  private static final int DEFAULT_SPEED = 500;
  private int speedCounter = 1;
  private int currentSpeed = DEFAULT_SPEED / speedCounter;
  private int squareX = 150;

  public TimerTest() {
    super("Test");
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    setMinimumSize(new Dimension(300, 200));
    setLayout(new BorderLayout());
    setLocationRelativeTo(null);

    JPanel displayPanel = new JPanel(null) {
      @Override
      public void paintComponent(Graphics g) {
        g.setColor(Color.RED);
        g.fillRect(squareX, getHeight() / 2, 25, 25);
      }
    };

    final Timer timer = new Timer(currentSpeed, new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        squareX = (squareX + 15) % getWidth();
        repaint();
      }
    });
    timer.setRepeats(true);

    JButton fastForwardButton = new JButton(new AbstractAction(">>") {
      @Override
      public void actionPerformed(ActionEvent e) {
        speedCounter++;
        currentSpeed = DEFAULT_SPEED / speedCounter;

        timer.stop();
        timer.setDelay(currentSpeed);
        timer.start();
      }
    });
    add(displayPanel, BorderLayout.CENTER);
    add(fastForwardButton, BorderLayout.SOUTH);
    timer.start();
  }
}

One noticeable flaw with this approach is that starting/stopping the timer will cause an additional delay. For example, say the timer was set to fire every 2 seconds and it has been 1.5 seconds since the last frame. If you set the delay to 1 second and restart the timer, 2.5 seconds will have passed before the next frame fires. This could explain why "it didn't work" for you.

To avoid this issue, you could create a timer that fires at some fixed rate but only executes your logic if enough time has passed. Then change what "enough time" is when the user fast-forwards. For example, the timer could fire every 50ms, but you only execute your logic if 500ms has passed since the last execution. When the user fast-forwards, you could then execute your logic if 250ms has passed instead (and so on).

DannyMo
  • 11,344
  • 4
  • 31
  • 37
  • For what ever reason, re writing it again similar to yours worked (even though mine is more or less the same XD) Thanks! – Terryn May 31 '13 at 22:00