首页 > 解决方案 > JavaFX Spinner 从场景中移除后继续运行

问题描述

我似乎在 JavaFX JDK Linux 1.8.0_144 中发现了 JavaFX Spinner 的问题。如果在从场景中移除微调器时按下递增或递减按钮,微调器将继续运行。

输出

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

代码

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

}

分析

Incom.sun.javafx.scene.control.skin.SpinnerSkin<T> com.sun.javafx.scene.control.behavior.SpinnerBehavior.stopSpinning()只在MOUSE_RELEASED事件中被调用。当微调器从场景中移除时,它会出现,此事件永远不会触发,并且不存在其他代码来停止旋转。

微调器被移除的事实是因为这个例子实际上来自一个更大的动态应用程序,其中屏幕可以从外部触发器自动更新。

问题

这是一个已知的错误还是我做错了什么?我怎样才能避免它?

标签: javajavafx

解决方案


这仍然是一个未解决的错误(我已经测试了 JavaFX 14.0.1)。我报告为JDK-8252863

我开发了以下解决方法,在场景更改为空时模拟鼠标释放。

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

推荐阅读