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

时间:2018-07-23 08:11:20

标签: multithreading javafx filechooser

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

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变量的值。

2 个答案:

答案 0 :(得分:2)

除非您需要使线程保持运行状态,否则建议通过在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访问数据,则如果同时修改数据,可能会遇到麻烦。

答案 1 :(得分:0)

不要像这样拆分方法。拥有export()之后,Platform.runLater()便无法继续。

选项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;
}
相关问题