JavaFX Spinner keeps going after removed from scene

Tags: ,



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?

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);
        }
    });
}


Source: stackoverflow