I appeared to have discovered a problem with JavaFX Spinner in JavaFX JDK Linux 1.8.0_144. If you are pressing on the increment or decrement button whilst a spinner is removed from the scene the spinner keeps going.
Output
Spinner update 501.0 Spinner update 502.0 Spinner update 503.0 Spinner update 504.0 Spinner update 505.0 Spinner update 506.0 Spinner removed from scene Spinner update 507.0 <== unexpected Spinner update 508.0 Spinner update 509.0 Spinner update 510.0 Spinner update 511.0 Spinner update 512.0
Code
import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Spinner; import javafx.scene.layout.HBox; import javafx.stage.Stage; import javafx.util.Duration; public class SpinnerProblem extends Application { @Override public void start(Stage primaryStage) throws Exception { Spinner<Double> spinner = new Spinner<>(0d, 1000d, 500d); spinner.valueProperty().addListener((obs, oldValue, newValue) -> { System.out.println("Spinner update " + newValue); }); HBox container = new HBox(spinner); primaryStage.setScene(new Scene(container)); primaryStage.show(); // remove the spinner from scene after 5 seconds Timeline timeline = new Timeline(); timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(5), event -> { System.out.println("Spinner removed from scene"); container.getChildren().clear(); })); timeline.play(); } public static void main(String[] args) { launch(args); } }
Analysis
In com.sun.javafx.scene.control.skin.SpinnerSkin<T>
com.sun.javafx.scene.control.behavior.SpinnerBehavior.stopSpinning()
is only ever called on MOUSE_RELEASED
event. It appears when spinner is removed from the scene this event is never triggered and no other code exists to stop the spinning.
The fact the spinner is removed is because this example is actually from a larger dynamic application where screens can update automatically from external triggers.
Question
Is this a known bug or something I’m doing wrong? How can I avoid it?
Advertisement
Answer
This remains an unresolved bug (I’ve tested as far as JavaFX 14.0.1). I’ve reported as JDK-8252863
I’ve developed the following workaround which simulates a mouse release in case Scene changes to null.
public static void monkeyPatchSpinnerBug(Spinner<?> spinner) { spinner.sceneProperty().addListener((obs, oldValue, newValue) -> { Node increment = spinner.lookup(".increment-arrow-button"); if (increment != null) { increment.getOnMouseReleased().handle(null); } Node decrement = spinner.lookup(".decrement-arrow-button"); if (decrement != null) { decrement.getOnMouseReleased().handle(null); } }); }