2
\$\begingroup\$

(See the next version here.)

Intro

I have this tiny JavaFX program that shows a 800x600 pixel canvas. You are supposed to drag the mouse within the canvas. When you are done dragging, the program will print in the standard output the number of frames per second.

For example, my system prints

196 frames in 1566 milliseconds, refresh rate of 125.15964240102171 Hz.

Code

com.github.coderodde.javafx.mouseupdaterate.MouseUpdateRateFinder.java:

package com.github.coderodde.javafx.mouseupdaterate;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
public final class MouseUpdateRateFinder extends Application {
 
 private static final int SCREEN_WIDTH = 800;
 private static final int SCREEN_HEIGHT = 600;
 
 public static void main(String[] args) {
 launch(args);
 }
 @Override
 public void start(Stage stage) throws Exception {
 Group root = new Group();
 Canvas canvas = new Canvas(SCREEN_WIDTH, SCREEN_HEIGHT);
 
 canvas.addEventHandler(MouseEvent.ANY, new MyMouseListener());
 
 root.getChildren().add(canvas);
 Scene scene = new Scene(root);
 stage.setScene(scene);
 stage.show();
 }
 
 private static final class MyMouseListener implements EventHandler<MouseEvent> {
 private long mouseButtonEventStart;
 private int frameCounter;
 
 @Override
 public void handle(MouseEvent t) {
 EventType<? extends MouseEvent> eventType = t.getEventType();
 
 if (eventType.equals(MouseEvent.MOUSE_PRESSED)) {
 mouseButtonEventStart = System.currentTimeMillis();
 frameCounter = 0;
 } else if (eventType.equals(MouseEvent.MOUSE_RELEASED)) {
 long duration = System.currentTimeMillis() 
 - mouseButtonEventStart;
 
 System.out.println(
 frameCounter 
 + " frames in " 
 + duration 
 + " milliseconds, refresh rate of " 
 + computeRefreshRate(duration, frameCounter) 
 + " Hz.");
 } else if (eventType.equals(MouseEvent.MOUSE_DRAGGED)) {
 frameCounter++;
 }
 }
 
 private double computeRefreshRate(long duration, int frameCounter) {
 double t = ((double) duration) / 1000.0;
 return ((double) frameCounter) / t;
 }
 }
}

Critique request

Is there any room for improvement? Please tell me anything.

asked Aug 23, 2023 at 11:22
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Your start doesn't actually throw any checked exceptions, so remove throw Exception (don't worry; this doesn't break override compatibility).

Writing an "everything handler" that then switches on event type is an anti-pattern; just register three separate handlers. You can use the new(ish) Java method reference sugar for this purpose. It's not strictly necessary to have a separate class but it's probably a good idea to keep it out of separation of concerns.

Might as well use nanoTime() instead of currentTimeMillis() for higher precision.

Avoid repeated-concatenation formatting; instead just use printf. When you do this, you should limit floating-point precision in your output.

Suggested

package com.github.coderodde.javafx.mouseupdaterate;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
public final class MouseUpdateRateFinder extends Application {
 private static final int SCREEN_WIDTH = 800;
 private static final int SCREEN_HEIGHT = 600;
 public static void main(String[] args) {
 launch(args);
 }
 @Override
 public void start(Stage stage) {
 Group root = new Group();
 MyMouseListener listener = new MyMouseListener();
 Canvas canvas = new Canvas(SCREEN_WIDTH, SCREEN_HEIGHT);
 canvas.addEventHandler(MouseEvent.MOUSE_PRESSED, listener::handlePressed);
 canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, listener::handleDragged);
 canvas.addEventHandler(MouseEvent.MOUSE_RELEASED, listener::handleReleased);
 root.getChildren().add(canvas);
 stage.setScene(new Scene(root));
 stage.show();
 }
 private static final class MyMouseListener {
 private long dragStartNs;
 private int frameCounter;
 public void handlePressed(MouseEvent t) {
 dragStartNs = System.nanoTime();
 frameCounter = 0;
 }
 public void handleDragged(MouseEvent t) {
 frameCounter++;
 }
 public void handleReleased(MouseEvent t) {
 double duration = 1e-9*(System.nanoTime() - dragStartNs);
 System.out.printf(
 "%d frames in %.2f s, refresh rate of %.1f Hz%n",
 frameCounter, duration, frameCounter / duration);
 }
 }
}

Output

155 frames in 1.61 s, refresh rate of 96.0 Hz
184 frames in 1.46 s, refresh rate of 126.2 Hz
answered Aug 23, 2023 at 14:15
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.