微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何正确地关闭javafx Alerts / fileChooser等

我正在看这个问题 JavaFX show dialogue after thread task is completed,但我的问题恰恰相反.在需要从用户返回一些数据的文件追踪器或警报之后,最好的方法是什么?

这就是我现在拥有的:

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

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

我知道这不是一个mvce,但我希望它能说明我在Platform.runLater调用中遇到的问题.

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

@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给出的 answer使用 FutureTask完美地工作.我想提供一个替代方案: CompletableFuture(在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一起使用.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐