javafx 使用
回想一下,给AnimationTimer起个名字可能不是一个好主意,因为它不仅可以用于动画,还可以用于测量fps速率,碰撞检测,模拟步骤,游戏主循环等。实际上,我大部分时间都在看AnimationTimer的运行与动画完全无关。
不过,在某些情况下,您可能要考虑为动画使用AnimationTimer。
这篇文章将解释该类,并显示一个示例,其中将AnimationTimer用于计算动画。
AnimationTimer提供了一个非常简单但非常有用且灵活的功能。
它允许指定一个方法,该方法将在每一帧中调用。
此方法的用途不受限制,并且如前所述,与动画没有任何关系。
唯一的要求是它必须快速返回,因为否则它很容易成为系统的瓶颈。
要使用它,开发人员必须扩展AnimationTimer并实现抽象方法handle()。
当AnimationTimer处于活动状态时,将在每一帧中调用此方法。
单个参数传递给handle()。
它包含当前时间(以纳秒为单位),与调用System.nanoTime()时的时间相同。
为什么要使用传入的值而不是自己调用System.nanoTime()或它的弟弟System.currentTimeMillis()?
有几个原因,但最重要的可能是,它使调试时的生活变得更加轻松。
如果您曾经尝试调试依赖于这两种方法的代码,那么您就知道自己已经基本陷入困境。
但是,JavaFX运行时在调试期间等待执行下一步时进入暂停状态,并且在此暂停期间内部时钟不会继续运行。
换句话说,无论您在调试时恢复暂停的程序之前等待两秒钟还是两个小时,参数的增量都将大致相同!
AnimationTimer有两个方法start()和stop()来激活和停用它。
如果覆盖它们,则在超类中调用这些方法很重要。
Animation API带有许多功能丰富的类,这些类使定义动画非常简单。
有预定义的过渡类,可以使用时间轴定义基于关键帧的动画,甚至可以轻松编写自定义过渡。
但是在什么情况下使用AnimationTimer有意义?
–几乎总是要使用标准类之一。
但是,如果要指定许多简单的动画,则最好使用AnimationTimer。
标准动画类的功能丰富性是有代价的。
每个动画都需要跟踪一大堆变量,而对于简单的动画,这些变量通常是不需要的。
另外,这些类针对速度进行了优化,而不是针对较小的内存占用。
有些变量存储两次,一次以公共API要求的格式存储,一次以有助于在播放时更快地计算的格式存储。
以下是显示星空的简单示例。
它为成千上万个从中心飞到外部边缘的矩形设置了动画。
使用AnimationTimer仅允许存储所需的值。
例如,与时间轴内的计算相比,该计算极其简单,因为无需考虑高级功能(循环,动画速率,方向等)。
package fxsandbox;
import java.util.Random;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class FXSandbox extends Application {
private static final int STAR_COUNT = 20000;
private final Rectangle[] nodes = new Rectangle[STAR_COUNT];
private final double[] angles = new double[STAR_COUNT];
private final long[] start = new long[STAR_COUNT];
private final Random random = new Random();
@Override
public void start(final Stage primaryStage) {
for (int i=0; i<STAR_COUNT; i++) {
nodes[i] = new Rectangle(1, 1, Color.WHITE);
angles[i] = 2.0 * Math.PI * random.nextDouble();
start[i] = random.nextInt(2000000000);
}
final Scene scene = new Scene(new Group(nodes), 800, 600, Color.BLACK);
primaryStage.setScene(scene);
primaryStage.show();
new AnimationTimer() {
@Override
public void handle(long now) {
final double width = 0.5 * primaryStage.getWidth();
final double height = 0.5 * primaryStage.getHeight();
final double radius = Math.sqrt(2) * Math.max(width, height);
for (int i=0; i<STAR_COUNT; i++) {
final Node node = nodes[i];
final double angle = angles[i];
final long t = (now - start[i]) % 2000000000;
final double d = t * radius / 2000000000.0;
node.setTranslateX(Math.cos(angle) * d + width);
node.setTranslateY(Math.sin(angle) * d + height);
}
}
}.start();
}
public static void main(String[] args) {
launch(args);
}
}
参考:在Mike's Blog博客上使用 JCG合作伙伴 Michael Heinrichs 的JavaFX AnimationTimer 。
翻译自: https://www.javacodegeeks.com/2012/06/using-javafx-animationtimer.html
javafx 使用