Java 应用程序活动期间发生应用程序挂断或“不在 FX 应用程序线程上”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24329395/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
App hangs up or "Not on FX application thread" occurs during app activity
提问by Dragon
The application reacts on actions which occur on gamepad. When button is pressed something happens on UI. But I ran at the issue with app hangs up or "java.lang.IllegalStateException: Not on FX application thread" exception.
应用程序对游戏手柄上发生的动作做出反应。当按下按钮时,UI 上会发生一些事情。但是我遇到了应用挂起或“java.lang.IllegalStateException:不在 FX 应用程序线程上”异常的问题。
In order to fix it I tried the following approaches: Platform.runLater()
and Task
usage. But it didn't help.
为了修复它,我尝试了以下方法:Platform.runLater()
和Task
用法。但它没有帮助。
Here is the problem code:
这是问题代码:
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()
emulates gamepad buttons activity polling. When user presses any button (rnd.nextInt(30) == 3
) - an image appears on the UI. When user releases that button (rnd.nextInt(30) == 7
) - an image disappears from the UI.
initStubGamepad()
模拟游戏手柄按钮活动轮询。当用户按下任何按钮 ( rnd.nextInt(30) == 3
) - UI 上会出现一个图像。当用户释放该按钮 ( rnd.nextInt(30) == 7
) - 图像从 UI 中消失。
In case above java.lang.IllegalStateException: Not on FX application thread
occurs. If you change runTask() to something like this:
java.lang.IllegalStateException: Not on FX application thread
发生上述情况时。如果你把 runTask() 改成这样:
Platform.runLater(new Runnable() {
@Override
public void run() {
initStubGamepad();
}
});
Then app will hang or even main UI won't appear at all, but gamepad activity continues.
然后应用程序将挂起,甚至根本不会出现主 UI,但游戏手柄活动仍在继续。
What I want is just to show/hide different images when some activity is detected on gamepad (btw, there's no way to monitor gamepad activity except for gamepad polling in an infinite loop). What did I wrong
我想要的只是在游戏手柄上检测到某些活动时显示/隐藏不同的图像(顺便说一句,除了游戏手柄在无限循环中轮询之外,没有办法监控游戏手柄活动)。我做错了什么
采纳答案by ItachiUchiha
Explanation
解释
In the first scenario, when you are using
在第一种情况下,当您使用
Task task = new Task<Void>() {
@Override
protected Void call() throws Exception {
initStubGamepad();
return null;
}
}
Inside initStubGamepad()
, which is running on a Task, you are trying to update the UI components inside pressBtn()
and releaseBtn()
methods, which is why you are facing a
Inside initStubGamepad()
,它在Task上运行,您正在尝试更新内部的 UI 组件pressBtn()
和releaseBtn()
方法,这就是为什么您面临
java.lang.IllegalStateException: Not on FX application thread
because all the UI updates must occur on the JavaFX thread
因为所有 UI 更新都必须在 JavaFX 线程上进行
In the second scenario, when you are using
在第二种情况下,当您使用
Platform.runLater(new Runnable() {
@Override
public void run() {
initStubGamepad();
}
});
the UI doesnt appear, because you have an infinite loopinside the initStubGamepad()
, which puts the JavaFX application thread run on an infinite loop
UI 没有出现,因为你在里面有一个无限循环initStubGamepad()
,这使得 JavaFX 应用程序线程在无限循环中运行
Solution
解决方案
By the time you have reach here, you must have already found the solution. In case you haven't, try try to put the update the Javafx components on the UI thread. So, instead of calling initStubGamepad()
inside Platform.runLater
, try calling pressBtn()
and releaseBtn()
inside it.
当您到达这里时,您一定已经找到了解决方案。如果您还没有,请尝试将更新 Javafx 组件放在 UI 线程上。因此,与其调用initStubGamepad()
inside Platform.runLater
,不如尝试调用pressBtn()
andreleaseBtn()
内部。
Try using
尝试使用
while (true) {
if (rnd.nextInt(30) == 3) {
Platform.runLater(() -> pressBtn());
} else if (rnd.nextInt(30) == 7) {
Platform.runLater(() -> releaseBtn());
}
}
or you may also use
或者你也可以使用
public void pressBtn() {
if(!isXPressed) {
Platform.runLater(() -> iv1.setVisible(true));
isXPressed = true;
}
}