JavaFX AnimationTimer似乎不同步,直到窗口调整大小

时间:2016-11-04 12:15:56

标签: javafx-8

一点介绍:我创建了一个简单的(现在)应用程序,它使用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);
    }
}

0 个答案:

没有答案