如何正确地关闭javafx Alerts / fileChooser等 [英] How to properly thread off javafx Alerts/fileChooser etc

查看:198
本文介绍了如何正确地关闭javafx Alerts / fileChooser等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在查看这个问题线程任务完成后JavaFX显示对话已完成,但我的问题恰恰相反。在文件追踪器或警报之后,如果您需要从用户那里获得一些数据,最好的方法是什么?

I was looking at this question JavaFX show dialogue after thread task is completed, but my question is kind of the opposite. What is the best way to thread off after a filechooser or alert where you need some data back from the user?

这就是我现在所拥有的:

Here's what I have now:

Platform.runLater(()->{
    File file = fileChooser.showOpenDialog(root.getScene().getWindow());
    if(file == null) {
        return;
    }
    executorService.execute(()->{
        //more code here which uses file
    });
});

其中executorService是先前创建的ExecutorService。我想我可以轻松地使用任务或线程或其他任何东西,但它如何被线程化无关紧要,只是因为它需要一段时间,我不希望在应用程序线程上发生它,因为它会锁定UI。

where executorService is an ExecutorService that was made earlier. I suppose I could just as easily use a Task or a Thread or anything else, but how it's threaded off doesn't matter, just that it's something that takes a while that I don't want to have happen on the Application thread because it would lock up the UI.

我知道这不是一个mvce,但我希望它能说明我在 Platform.runLater 来电。

I know this isn't an mvce, but I hope it demonstrates the problem I'm having with threads inside Platform.runLater calls.

这是一个极端的例子,说明这种事情有多复杂

Here's an extreme example of how convoluted this kind of thing gets

@FXML
public void copyFiles(ActionEvent event){
    //this method is on the application thread because a button or something started it
    // so we thread off here
    executorService.execute(()->{
        // do some stuff
        // ...
        // get location to copy to from user
        // must happen on the application thread!
        Platform.runLater(()->{
            File file = fileChooser.showOpenDialog(root.getScene().getWindow());
            if(file == null) {
                return;
            }
            executorService.execute(()->{
                // more code here which uses file
                // ...
                // oh wait, some files have the same names! 
                // we need a user's confirmation before proceeding
                Platform.runLater(()->{
                    Alert alert = new Alert(AlertType.CONFIRMATION, "Do you want to overwrite files with the same names?", ButtonType.OK, ButtonType.CANCEL);
                    Optional<ButtonType> choice = alert.showAndWait();
                    if(choice.isPresent && choice.get == ButtonType.OK){
                        // do something, but not on the application thread
                        executorService.execute(()->{
                            // do the last of the copying
                            // ...
                        });
                    }
                });
            });
        });
    });
}


推荐答案

看来你的问题是需要的在后台任务中间的信息,只能在JavaFX Application线程上检索。 James_D给出的答案使用 FutureTask 。我想提供一个替代方案: CompletableFuture (在Java 8中添加)。

It seems your issue is needing information in the middle of a background task that can only be retrieved while on the JavaFX Application thread. The answer given by James_D works perfectly for this using FutureTask. I'd like to offer an alternative: CompletableFuture (added in Java 8).

public void copyFiles(ActionEvent event) {

    executorService.execute(() -> {

        // This uses CompletableFuture.supplyAsync(Supplier, Executor)

        // need file from user
        File file = CompletableFuture.supplyAsync(() -> {
            // show FileChooser dialog and return result
        }, Platform::runLater).join(); // runs on FX thread and waits for result

        if (file == null) {
            return;
        }

        // do some stuff

        // ask for confirmation
        boolean confirmed = CompletableFuture.supplyAsync(() -> {
            // show alert and return result
        }, Platform::runLater).join(); // again, runs on FX thread and waits for result

        if (confirmed) {
            // do more stuff
        }

    });
}

两者 FutureTask CompletableFuture 将适合您。我更喜欢 CompletableFuture ,因为它提供了更多选项(如果需要),并且 join()方法不会检查像 get()这样的例外。但是, CompletableFuture Future (就像 FutureTask )所以你仍然可以使用 get()一个 CompletableFuture

Both FutureTask and CompletableFuture will work for you. I prefer CompletableFuture because it it provides more options (if needed) and the join() method doesn't throw checked exceptions like get() does. However, CompletableFuture is a Future (just like FutureTask) and so you can still use get() with a CompletableFuture.

这篇关于如何正确地关闭javafx Alerts / fileChooser等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆