Java FX : Unable to open popup from different FX thread

标签 java multithreading javafx concurrency

您好,我有一个可以在 GUI(Java FX)和命令行上运行的应用程序。 当作为 GUI 运行时,我在文本区域显示状态。这工作得很好。

但问题是,当我尝试显示来自某个不同(非 javafx)类的错误(通过弹出窗口)时,它会向我显示 Java Fx - 线程异常不在 FX 线程上。

下面是我的代码

这是我的 Java FX 类,我希望在其中显示弹出窗口。

public class DeploymentProcesController implements Initializable {


@FXML
private TextArea statusTextArea;

@Override
public void initialize(URL location, ResourceBundle resources) {

}

public void updateGUIMessage(String message) {
    if (Platform.isFxApplicationThread()) {
        statusTextArea.appendText(message);
    } else {
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                statusTextArea.appendText(message);
            }
        });
    }
}

public void displayAlertMessages(final String message) {
    Platform.setImplicitExit(false);
    Task<Void> task = new Task<Void>() {
        @Override public Void call() {
            Platform.runLater(new Runnable() {
                public void run() {
                    Alert alert = new Alert(AlertType.INFORMATION, message, ButtonType.OK);
                    alert.showAndWait();
                }
            });

            return null;
        }
    };
    new Thread(task).start();
}

}

我有一个非 FX 类,它是入口点。因此,根据运行类型(命令行/GUI)我更新状态。

这是我打电话更新状态的方式。

public void promptUser(String message,boolean isCommandLineRun){
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    if(isCommandLineRun) {
        System.out.println(simpleDateFormat.format(new Date()) + " - " + message);
    } else {
        controller.displayAlertMessages(message);
    }
}

当我从非 fx 类调用 updateGUIMessage 方法时没有任何问题。这是因为 statusArea 元素位于 FX 线程上(该 fx 类的成员)。

此外,我在单击某些按钮时生成警报框没有任何问题, 但要显示来自不同类的警报框 - 我遇到了问题,因为一旦我尝试生成警报框,应用程序就会崩溃,说不在 fx 线程上。

据我了解,警报框是弹出窗口,因此可能无法处理。但是任何人都可以帮助我,我想向用户显示一个来自不同类别的警报框。

最佳答案

假设您希望在调用弹出窗口之前运行一些长时间运行的代码, 处理 Fx 按钮时需要完成两个步骤。第一个线程让代码在按下按钮时作为线程运行。第二个是 Platform.runlater(),它告诉 Fx 平台从平台执行该线程中的代码。请注意,只有在外线程中到达 runlater 时,才会执行弹出窗口。 否则您可以直接调用弹出窗口。

public void MyExampleBtn() {
  Thread t = new Thread() {
    // long running work to be done, threaded so as not to hang the main controls.
    // .... 
    // work is done do the success popup
    @Override
      public void run() {
      Platform.runLater(new Runnable() {
       @Override
         public void run() {
           Alert alert = new Alert(AlertType.INFORMATION);
           alert.setTitle("Success!");
           alert.setHeaderText(null);
           alert.setContentText("This is my popup");
           alert.showAndWait();
         }
       });
     }
   };
}

关于Java FX : Unable to open popup from different FX thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37791948/

相关文章:

java - 通过JUNIT运行程序时如何打印值(用于调试)

swift - 断言在应该传递 : why? 的地方失败

JavaFX 使用非 JavaFX 线程的 UI 中使用的提取器更新 ObservableList

java - 如何向按钮添加方法以在 JavaFX 中的场景之间切换

java - ProgressIndicator(节点)作为鼠标光标?

java - 更改内部类中变量的值

java - 我怎样才能在 swt 中放置一个小部件并在同一个地方再次创建该小部件?

java - 在线程安全单例中,返回是否必须在同步块(synchronized block)内

java - 如何让Java JPA创建实体?

java - SwingWorker:未调用 process() 方法