您好我有应用程序,它在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线程上。
我知道“警报”框是一个弹出窗口,因此可能未处理。但是,任何人都可以帮助我,我想向用户展示来自不同班级的警报框。
答案 0 :(得分:1)
UI中的所有内容都必须从UI应用程序线程执行。这正是错误信息的含义。
幸运的是,您可以简单地将您的调用包装起来,以便在UI线程中执行:
if(isCommandLineRun) {
System.out.println(simpleDateFormat.format(new Date()) + " - " + message);
} else {
Platform.runLater(() -> controller.displayAlertMessages(message));
}
答案 1 :(得分:0)
终于找到了解决方案,
由于Java fx在单线程上运行,所以一切都必须在同一个线程上。对于需要暂停背景的每个任务(例如弹出窗口),我们需要使用FutureTask。
我在这里找到了这篇文章:
答案 2 :(得分:0)
假设您要在调用弹出窗口之前运行一些长时间运行的代码, 处理Fx按钮时,需要完成两个步骤。当按下按钮时,第一个线程使代码作为线程运行。第二个是Platform.runlater(),它告诉Fx Platform从Platform执行该线程中的代码。请注意,直到在外部线程中达到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();
}
});
}
};
}