应用程序会对游戏 handle 上发生的操作使用react。当按下按钮时,用户界面上会发生一些事情。但我遇到了应用程序挂起或“java.lang.IllegalStateException:不在 FX 应用程序线程上”异常的问题。
为了修复它,我尝试了以下方法:Platform.runLater()
和 Task
使用。但这并没有帮助。
这是问题代码:
public class GamepadUI extends Application{
private static final int WIDTH = 300;
private static final int HEIGHT = 213;
private Pane root = new Pane();
private ImageView iv1 = new ImageView();
private boolean isXPressed = false;
@Override
public void start(Stage stage) throws Exception {
initGUI(root);
Scene scene = new Scene(root, WIDTH, HEIGHT);
stage.setScene(scene);
stage.setResizable(false);
stage.show();
}
public void pressBtn() {
if(!isXPressed) {
iv1.setVisible(true);
isXPressed = true;
}
}
public void releaseBtn() {
if(isXPressed) {
iv1.setVisible(false);
isXPressed = false;
}
}
private void initGUI(final Pane root) {
Image image = new Image(Props.BUTTON);
iv1.setImage(image);
iv1.setLayoutX(198);
iv1.setLayoutY(48);
iv1.setVisible(false);
root.getChildren().add(iv1);
runTask();
}
public void runTask() {
Task task = new Task<Void>() {
@Override
protected Void call() throws Exception {
initStubGamepad();
return null;
}
};
new Thread(task).start();
}
public static void main(String[] args) {
launch(args);
}
public void initStubGamepad() {
Random rnd = new Random();
try {
while (true) {
if (rnd.nextInt(30) == 3) {
pressBtn();
} else if (rnd.nextInt(30) == 7) {
releaseBtn();
}
}
} catch (Exception ex) {
System.out.println("Exception: " + ex);
}
}
}
initStubGamepad()
模拟游戏 handle 按钮 Activity 轮询。当用户按下任何按钮时 (rnd.nextInt(30) == 3
) - UI 上会出现一个图像。当用户释放该按钮时 (rnd.nextInt(30) == 7
) - 图像从 UI 中消失。
在上述情况下,发生java.lang.IllegalStateException:不在 FX 应用程序线程上
。如果将 runTask() 更改为如下所示:
Platform.runLater(new Runnable() {
@Override
public void run() {
initStubGamepad();
}
});
然后应用程序将挂起,甚至主 UI 根本不会出现,但游戏 handle Activity 仍在继续。
我想要的只是在游戏 handle 上检测到某些 Activity 时显示/隐藏不同的图像(顺便说一句,除了无限循环中的游戏 handle 轮询之外,没有办法监视游戏 handle Activity )。我做错了什么
最佳答案
说明
在第一个场景中,当您使用时
Task task = new Task<Void>() {
@Override
protected Void call() throws Exception {
initStubGamepad();
return null;
}
}
在 Task 上运行的 initStubGamepad()
中,您尝试更新 pressBtn()
和 releaseBtn()
方法中的 UI 组件,这就是您面临
java.lang.IllegalStateException: Not on FX application thread
因为所有 UI 更新都必须发生在 JavaFX 线程上
在第二种情况中,当您使用时
Platform.runLater(new Runnable() {
@Override
public void run() {
initStubGamepad();
}
});
UI 没有出现,因为 initStubGamepad()
中有一个无限循环,这使得 JavaFX 应用程序线程在无限循环上运行
解决方案
当你到达这里时,你一定已经找到了解决方案。如果还没有,请尝试将 Javafx 组件的更新放在 UI 线程上。因此,不要在 Platform.runLater
中调用 initStubGamepad()
,而是尝试在其中调用 pressBtn()
和 releaseBtn()
。
尝试使用
while (true) {
if (rnd.nextInt(30) == 3) {
Platform.runLater(() -> pressBtn());
} else if (rnd.nextInt(30) == 7) {
Platform.runLater(() -> releaseBtn());
}
}
或者您也可以使用
public void pressBtn() {
if(!isXPressed) {
Platform.runLater(() -> iv1.setVisible(true));
isXPressed = true;
}
}
关于java - 应用程序 Activity 期间发生应用程序挂起或 "Not on FX application thread",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35222886/