Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the preferred way of getting the frame rate of a JavaFX application?

Tags:

javafx

This is quite a simple question:

What is the preferred way of getting the frame rate of a JavaFX application?

Google turns up a result from 2009, but that example pertains to JavaFX 1.x and operates in a weird way (some sort of external meter) to begin with. Not being able to find a better example, I am posting here.

I want to be able to query my JavaFX application (or if necessary, the current scene) and get what the current FPS is.

Update: Feb. 8th 2015

Various solutions to the problem are posted below as answers. I also found that this question was referenced by the following blog post: http://tomasmikula.github.io/blog/2015/02/08/measuring-fps-with-reactfx.html

Which says that (as a result of the verbosity of the solutions below) measuring FPS was added to ReactFX 2.0 milestone 2. Cool how things travel.

like image 363
brcolow Avatar asked Feb 02 '15 21:02

brcolow


1 Answers

You can use an AnimationTimer.

The AnimationTimer's handle method is called once on each frame, and the value passed in is the current time in nanoseconds (a best approximation). So you can track how long since the previous frame.

Here's an implementation that tracks the times of the last 100 frames and computes the frame rate using them:

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class SimpleFrameRateMeter extends Application {

    private final long[] frameTimes = new long[100];
    private int frameTimeIndex = 0 ;
    private boolean arrayFilled = false ;

    @Override
    public void start(Stage primaryStage) {

        Label label = new Label();
        AnimationTimer frameRateMeter = new AnimationTimer() {

            @Override
            public void handle(long now) {
                long oldFrameTime = frameTimes[frameTimeIndex] ;
                frameTimes[frameTimeIndex] = now ;
                frameTimeIndex = (frameTimeIndex + 1) % frameTimes.length ;
                if (frameTimeIndex == 0) {
                    arrayFilled = true ;
                }
                if (arrayFilled) {
                    long elapsedNanos = now - oldFrameTime ;
                    long elapsedNanosPerFrame = elapsedNanos / frameTimes.length ;
                    double frameRate = 1_000_000_000.0 / elapsedNanosPerFrame ;
                    label.setText(String.format("Current frame rate: %.3f", frameRate));
                }
            }
        };

        frameRateMeter.start();

        primaryStage.setScene(new Scene(new StackPane(label), 250, 150));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
like image 144
James_D Avatar answered Sep 19 '22 15:09

James_D