【问题标题】:Java Timer Swing Exactly 60 fpsJava Timer Swing 精确到 60 fps
【发布时间】:2016-07-23 02:54:18
【问题描述】:

我在 JPanel 中有一个动画,它通过 javax.swing.Timer 进行自我更新。可以将此计时器构造为以毫秒为单位的延迟,该延迟必须是整数。如果我让 JPanel 每秒更新 60 次,我会将延迟设置为 1000/60 = ~16.6666。但是,这个延迟必须是一个整数,所以我可以选择向上或向下舍入。对于 16 毫秒的延迟,动画将以每秒 62.5 帧的速度更新。将延迟四舍五入到 17 毫秒会得到 58.824 的帧速率。

如何获得每秒 60 帧的帧速率?

提前致谢。

【问题讨论】:

  • 系统计时器的分辨率通常约为 15 毫秒。因此,无论如何,您都不太可能获得所需的精确分辨率。
  • 即使系统计时器不准确,它也应该随着时间的推移平均错误(如果我的逻辑没有错的话)并且仍然给出相同的、不受欢迎的帧速率(上图)。

标签: java swing timer frame-rate


【解决方案1】:

我看到了两个可以帮助您的选项。他们最终以同样的方式实现同​​样的事情,但代码或多或少是通用的。我还没有找到任何可以为您完成这项工作的工具,因此需要做一些工作。

第一种选择是这样做:

/**
 * 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));
}

第二个选项是让您获取 java.util.Timer 的副本: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Timer.java

并重写特定于毫秒的位。在 OpenJDK 中的实现中没有任何内容表明它的分辨率是特定于毫秒的,因此您应该能够将 Object.wait(millis) 调用替换为 Object.wait(millis, nanos): https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait(long,%20int)

有趣的文章,仅供娱乐:https://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks

【讨论】:

  • 这个答案看起来像java.util.Timer,而不是必须使用javax.swing.Timer的Swing应用程序。
【解决方案2】:

没有那么复杂!您可以轻松地完成 repaint() 或任何其他您需要准确调用的方法每秒 60 次,其中存在单个最大循环

while(true) {
    repaint ();
    try {
         Thread.sleep(1000/60);
    } catch (InterruptedException e) {
    }
}

我在脚本的 main 方法中调用它,但基本上它是一个无限循环,因为 true 总是等于 true,然后它调用 repaint,告诉循环休眠一帧,然后再次调用 repaint。而 1000/60 的睡眠将导致该循环每秒准确调用 60 次

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-26
    相关资源
    最近更新 更多