How to properly close JavaFX alerts / filechooser, etc

I am looking at this problem JavaFX show dialogue after thread task is completed, but my problem is just the opposite After a file tracker or alert that needs to return some data from the user, what is the best way?

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

Where executorservice is the executorservice created previously I think I can easily use tasks or threads or anything else, but it doesn't matter how it is threaded, just because it takes a while. I don't want it to happen on the application thread because it locks the UI

I know this is not an mvce, but I hope it can show me on platform Problem encountered in runlater call

This is an extreme example of how complex this is

@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
                            // ...
                        });
                    }
                });
            });
        });
    });
}

Solution

It seems that your problem is that you need the information in the middle of the background task, which can only be retrieved on the JavaFX application thread James_ The answer given by D works perfectly using futuretask I want to offer an alternative: completable future (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
        }

    });
}

Both futuretask and completable future are suitable for you I prefer completable future because it provides more options (if needed) and the join () method does not throw checked exceptions like get () However, completable future is future (just like futuretask), so you can still use get () with completable future

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>