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.
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With