在 JavaFX 应用程序中更改光标以进行长时间操作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20556945/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 02:47:38  来源:igfitidea点击:

Changing cursor in JavaFX application for long operations

javajavafx

提问by Nik?a Baldun

I would like to change the cursor to Cursor.WAIT when executing potentially long operations in JavaFX application. I thought that Platform.runLater will help me:

在 JavaFX 应用程序中执行潜在的长操作时,我想将光标更改为 Cursor.WAIT。我认为 Platform.runLater 会帮助我:

this.getStage().getScene().setCursor(Cursor.WAIT);

Platform.runLater(new Runnable() {
    @Override
    public void run() {
        // Do some stuff
        getStage().getScene().setCursor(Cursor.DEFAULT);
    }
});

But cursor does not change. Why doesn't this work?

但光标不会改变。为什么这不起作用?

采纳答案by jewelsea

Assuming you are running the following code off of the JavaFX Application thread, a pattern for displaying a wait cursor could be:

假设您从 JavaFX 应用程序线程运行以下代码,显示等待光标的模式可能是:

Platform.runLater(new Runnable() {
    @Override
    public void run() {
        getStage().getScene().setCursor(Cursor.WAIT);
    }
});

// Do some stuff

Platform.runLater(new Runnable() {
    @Override
    public void run() {
        getStage().getScene().setCursor(Cursor.DEFAULT);
    }
});

Or, if you are already on the JavaFX application thread, you could use a Service:

或者,如果您已经在 J​​avaFX 应用程序线程上,则可以使用Service

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.concurrent.*;
import javafx.event.*;
import javafx.geometry.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ServiceWithCursorControl extends Application {
    private final Button runButton = new Button("Run");
    private final Label label = new Label();

    private final Service service = new Service() {
        @Override
        protected Task createTask() {
            return new Task<Void>() {
                @Override protected Void call() throws Exception {
                    // do stuff
                    Thread.sleep(5000);
                    return null;
                }
            };
        }
    };

    @Override public void start(Stage stage) {
        VBox layout = createLayout();

        Scene scene = new Scene(layout, 100, 80);
        stage.setScene(scene);

        bindUIandService(stage);

        stage.show();
    }

    private void bindUIandService(Stage stage) {
        label.textProperty()
                .bind(
                        service.stateProperty().asString()
                );

        stage.getScene()
                .getRoot()
                .cursorProperty()
                .bind(
                        Bindings
                            .when(service.runningProperty())
                                .then(Cursor.WAIT)
                                .otherwise(Cursor.DEFAULT)
                );

        runButton
                .disableProperty()
                .bind(
                        service.runningProperty()
                );

        runButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                service.restart();
            }
        });
    }

    private VBox createLayout() {
        VBox layout = new VBox(10);

        layout.getChildren().setAll(runButton, label);
        layout.setPadding(new Insets(10));
        layout.setAlignment(Pos.CENTER);

        return layout;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

It's unclear from your description which approach fits your problem best, but hopefully you can work it out.

从您的描述中不清楚哪种方法最适合您的问题,但希望您能解决。