一点介绍:我创建了一个简单的(现在)应用程序,它使用AnimationTimer
来更新动画并将对象绘制到Canvas
。一切运行顺利,计时器将其fps调整到笔记本电脑的刷新率(50 / 60Hz)。
然而,当我启动程序时,似乎有一些错误导致我的动画显示为“jurky”或丢帧,但帧速率保持稳定60 / 50fps。然后,当我第一次调整窗口大小(没有多少差异)时,突然所有的动画都非常流畅。在那之后,无论调整大小如何,一切都保持“同步”。
AnimationTimer
在窗口调整大小之前启动“不同步”的原因是什么?可以阻止它吗?
添加了一个代码示例。这个问题在50Hz时基本上是可见的,但也存在于60Hz。在Windows 10上使用Eclipse(第一个代码共享,可能是很多/缺少的东西)。
public void start(Stage primaryStage) {
try {
pane = new Pane();
drawables = new ArrayList<>();
canvas = new Canvas(400,400);
canvas.widthProperty().bind(pane.widthProperty());
canvas.heightProperty().bind(pane.heightProperty());
GraphicsContext g = canvas.getGraphicsContext2D();
SimpleAnimatedCircle circle = new SimpleAnimatedCircle(20);
circle.setX(100);
circle.setY(50);
timer = new AnimationTimer() {
@Override
public void handle(long now) {
frameCount++;
if (System.currentTimeMillis() > frameStart + 500) {
System.out.println("FPS: " + frameCount*2);
frameStart = System.currentTimeMillis();
frameCount = 0;
}
for (Drawable drawable:drawables) {
drawable.update();
}
g.setFill(Color.DARKSLATEBLUE);
g.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
circle.draw(g);
}
};
timer.start();
canvas.setOnMouseClicked((e) -> {
circle.start();
});
pane.getChildren().add(canvas);
Scene scene = new Scene(pane,400,400);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static class SimpleAnimatedCircle {
double diameter;
double x;
double y;
long startTime;
double diffY = 300; // Animated distance over y-axis.
double duration = 2000; // 2 second duration.
public SimpleAnimatedCircle(double diameter) {
this.diameter = diameter;
}
public void setX(double value) {
x = value;
}
public void setY(double value) {
y = value;
}
public void start() {
startTime = System.currentTimeMillis();
}
public void draw(GraphicsContext g) {
double animatedY = y;
// Update the animation.
if (System.currentTimeMillis() < startTime + duration) {
animatedY = y + (System.currentTimeMillis() - startTime) /
duration * diffY;
}
g.setFill(Color.ORANGE);
g.fillOval(x, animatedY, diameter, diameter);
}
}