'不在外汇申请线程'从加载了FXML作为内容的对话框启动线程时出错

时间:2015-01-04 11:19:13

标签: java javafx dialog javafx-8

我目前有以下情况:

我创建了一个 JavaFX 应用程序,其中包含一个用于打开对话框的屏幕(只需单击屏幕上的按钮)。然后,用户输入并单击“应用”按钮。然后将用户输入发送到方法,该方法打开某种进度对话框(用于向用户显示同步的状态,这对于该问题并不重要)。我将此对话框称为' MyDialog' 。 MyDialog使用以下代码构建:

Dialog<Void> dialog = new Dialog<>();
dialog.initOwner(null);
dialog.initStyle(StageStyle.UNDECORATED);
dialog.setHeaderText("Nieuw product synchroniseren...");
dialog.setResizable(false);

//Load dialog FXML file into the Pane
FXMLLoader fxmlloader = new FXMLLoader();
fxmlloader.setLocation(getClass().getResource("dialogs/MyDialogContent.fxml"));
try {
    dialog.getDialogPane().setContent(fxmlloader.load());
} catch (IOException e) {
    Functions.createExceptionDialog(e);
}
MyDialogContentController childController = fxmlloader.getController();

final ButtonType canceledButtonType = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
dialog.getDialogPane().getButtonTypes().add(canceledButtonType);

这很好用。 MyDialog中显示的ProgressBar表示任务的进度。该任务从线程开始。该线程从上部屏幕的控制器启动。在任务中,我想在某个时候显示一个额外的对话框,以获得一些用户验证。我将此对话框称为&#39; AlertDialog&#39; 。这是该部分的代码(放置在上部屏幕的Controller中,而不是在MyDialog的Controller中):

Task<Object> task = new Task<Object>() {

    @Override
    protected Object call() {
        //Show choice dialog
        Alert alert = new Alert(AlertType.CONFIRMATION);
        alert.initOwner(null);
        alert.initStyle(StageStyle.UNDECORATED);

        ButtonType buttonTypeOne = new ButtonType("One");
        ButtonType buttonTypeTwo = new ButtonType("Two");
        ButtonType buttonTypeThree = new ButtonType("Three");
        ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);

        alert.getButtonTypes().setAll(buttonTypeOne, buttonTypeTwo, buttonTypeThree, buttonTypeCancel);

        Optional<ButtonType> result = alert.showAndWait();

        if (result.get() == buttonTypeOne){
            //User chose "One";
        } else if (result.get() == buttonTypeTwo) {
            // ... user chose "Two"
        } else if (result.get() == buttonTypeThree) {
            // ... user chose "Three"
        } else {
            // ... user chose CANCEL or closed the dialog
        }
    }
}

不幸的是,AlertDialog没有显示,我收到以下错误:

Exception in thread "Thread-10" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-10

我已尝试过以下解决方案:

  • 将AlertDialog代码放在MyDialogController中,然后从任务中调用它。
  • 从MyDialogController启动线程,而不是从上部屏幕控制器启动。然后通过&#39; childController.thread&#39;。
  • 调用它

这两种解决方案都不起作用。我希望它与在DialogPane中加载FXML文件有关,因此与线程及其启动位置有关。

所以这种情况下的问题是:

  1. 为什么会出现此错误?

  2. 错误与AlertDialog没有显示有关吗?

  3. 我对这部分代码的处理方法是否应该有所不同? (例如,不在对话框中加载外部FXML文件)

  4. 非常感谢任何帮助!

1 个答案:

答案 0 :(得分:4)

我觉得我已经在SO上写了100次了......又一次:JavaFX是一个单线程的GUI,因此每个与GUI相关的东西都必须在主JavaFX Thread上完成。

如果您尝试从JavaFX线程中执行与GUI相关的操作,您将获得IllegalStateException: Not on FX application thread

Optional<ButtonType> result = alert.showAndWait();是一项GUI操作,因为您初始化并显示Dialog。因此,您应该在其他地方检索用户输入,并且只在后台执行长时间运行的计算。

用户输入的优点是例如Task类的各种生命周期挂钩(如succeeded()failed())。