JavaFX 等待 FileChooser showSaveDialog 获取选择的文件路径

JavaFX wait FileChooser showSaveDialog to get selected file path

我想从 JavaFX 中的 FileChooser showSaveDialog() 对话框中获取选定的文件路径,以便将表视图导出到文件。 代码在 Runnable 中 运行ning,所以我必须 运行 JavaFX 主线程中的 showSaveDialog (Platform.runLater)

public class ExportUtils {
  ...
  private File file = null;
  private String outputPath = null;

  public void Export(){
   ...
   ChooseDirectory(stage);
   if (outputPath != null{
      ...   //export to the selected path
   }
  }

  public void ChooseDirectory(Stage stage) {
      ...
      FileChooser newFileChooser = new FileChooser();
      ...

      Platform.runLater(new Runnable() {
        public void run() {
            file = newFileChooser.showSaveDialog(stage);
            if (file != null) {
                outputPath = file.getPath();
            }
        }
    });
}

我想知道这种情况的最佳解决方案,在这种情况下,我必须等待用户选择路径和文件名,然后才能在 Export() 方法中评估 outputPath 变量的值。

不要这样拆分方法。 Platform.runLater().

之后,您的 export() 无法继续

选项 1

把所有的东西合二为一。

public void export() {
    ...

    Platform.runLater(new Runnable() {
        public void run() {
            file = new FileChooser().showSaveDialog(stage);
            if (file != null) {
                outputPath = file.getPath();

                // Export to the path
            }
        }
    });
}

选项 2

您可以将 Platform.runLater() 移动到 export() 的开头。

public void export() {
    ...
    Platform.runLater(() -> {
        String outputPath = chooseDirectory(stage);
        if (outputPath != null) {
            // Export to the path
        }
    });
}

private String chooseDirectory(Stage stage) {
    ...
    file = new FileChooser().showSaveDialog(stage);
    if (file != null) {
        return file.getPath();
    }
    else return null;
}

除非您需要保留线程 运行 我建议通过启动新线程而不是在 ExecutorService.

上发布任务来处理文件选择

如果您确实需要这样做,您可以使用 CompletableFuture 来检索结果:

private static void open(Stage stage, CompletableFuture<File> future) {
    Platform.runLater(() -> {
        FileChooser fileChooser = new FileChooser();
        future.complete(fileChooser.showSaveDialog(stage)); // fill future with result
    });
}

@Override
public void start(Stage primaryStage) throws Exception {
    Button button = new Button("start");

    button.setOnAction(evt -> {
        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                CompletableFuture<File> future = new CompletableFuture<>();
                open(primaryStage, future);
                try {
                    File file = future.get(); // wait for future to be assigned a result and retrieve it
                    System.out.println(file == null ? "no file chosen" : file.toString());
                } catch (InterruptedException | ExecutionException ex) {
                    ex.printStackTrace();
                }
            }
        }).start();
    });

    primaryStage.setScene(new Scene(new StackPane(button)));
    primaryStage.show();

}

注意:如果您在单独的线程中访问来自ui的数据,如果同时修改数据,您可能会遇到麻烦。