加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-15 08:26:01 所属栏目:Java 来源:网络整理
导读:我正在看这个问题 JavaFX show dialogue after thread task is completed,但我的问题恰恰相反.在需要从用户返回一些数据的文件追踪器或警报之后,最好的方法是什么? 这就是我现在拥有的: Platform.runLater(()-{ File file = fileChooser.showOpenDialog(ro
我正在看这个问题 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一起使用.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读