gpt4 book ai didi

java - 如何正确关闭 javafx Alerts/fileChooser 等

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:38:29 47 4
gpt4 key购买 nike

我在看这个问题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。我想我可以轻松地使用 Task 或 Thread 或其他任何东西,但它如何线程化并不重要,只是它需要一段时间,我不想在应用程序线程上发生,因为它会锁定用户界面。

我知道这不是 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
// ...
});
}
});
});
});
});
}

最佳答案

如果您需要在返回结果的 UI 线程上执行某些操作,请创建一个 FutureTask,将其提交给 UI 线程,然后在后台线程上等待它完成。这允许您“扁平化”代码。

您还可以将 Platform.runLater(...) 抽象为 Executor(毕竟,它只是执行 Runnable 的东西s),这可以使它(也许)稍微干净一些。

通过划分成更小的方法(并且通常只使用其他标准编程技术),您可以使代码非常干净。

这是基本思想(您需要添加异常处理,或创建一个 Callable(它可以抛出异常)而不是 Runnable):

@FXML
public void copyFiles(ActionEvent event){

Executor uiExec = Platform::runLater ;

//this method is on the application thread because a button or something started it
// so we thread off here

Callable<Void> backgroundTask = () -> {
doFirstTimeConsumingThing();

FutureTask<File> getUserFile = new FutureTask<>(this::getUserFile) ;
uiExec.execute(getUserFile);
File file = getUserFile.get();
if (file == null) return null ;

doAnotherTimeConsumingThing(file);
FutureTask<Boolean> getUserConfirmation = new FutureTask<>(this::showConfirmation);
uiExec.execute(getUserConfirmation);
if (! getUserConfirmation.get()) return null ;

doMoreTimeConsumingStuff();

// etc...

return null ;
};
executorService.execute(backgroundTask);
}

private File getUserFile() {
return fileChooser.showOpenDialog(root.getScene().getWindow());
}

private Boolean getUserConfirmation() {
Alert alert = new Alert(AlertType.CONFIRMATION, "Do you want to overwrite files with the same names?", ButtonType.OK, ButtonType.CANCEL);
return alert.showAndWait()
.filter(ButtonType.OK::equals)
.isPresent();
}

private void doFirstTimeConsumingThing() {
// ...
}

private void doAnotherTimeConsumingThing(File file) {
// ....
}

private void doMoreTimeConsumingStuff() {
// ...
}

关于java - 如何正确关闭 javafx Alerts/fileChooser 等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50067565/

47 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com