Search code examples
javaswingtimerframe-rate

Java Timer Swing Exactly 60 fps


I have an animation in a JPanel that updates itself through a javax.swing.Timer. This timer can be constructed to have a delay in milliseconds that must be an integer. If I were to have the JPanel update 60 times each second, I would set the delay to 1000/60 = ~16.6666. However, this delay must be an int, so I have the option of rounding up or down. For a delay of 16 milliseconds, the animation would update at 62.5 frames per second. Rounding up to 17 millisecond delay would give a frame rate of 58.824.

How would I go about having a frame rate of exactly 60 frames per second?

Thanks in advance.


Solution

  • I see two options which could help you. They ultimately achieve the same thing in the same way, but the code is more or less general. I haven't found any tool out there that does the job for you, so it requires a little bit of work.

    The first option is to do something like this:

    /**
     * Called by the timer when the next iteration is due. Assume that
     * this happens at the right moment.
     */
    public void onTimerUpdate() {
      updateAnimation();
    
      // Compute the next point in time that corresponds to the
      // frame rate you want.
      long nextScheduledTimestamp = getNextTimestampInNanos();
    
      long nanos = System.timeNanos();
      timer.schedule(task, convertToMillis(nextScheduledTimestamp - nanos));
    }
    

    The second option is for you to get your copy of java.util.Timer: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Timer.java

    and rewrite the bits that are millisecond-specific. Nothing in its implementation in OpenJDK shows that its resolution is millisecond specific, so you should be able to replace Object.wait(millis) calls with Object.wait(millis, nanos): https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait(long,%20int)

    Interesting article, just for fun: https://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks