问题描述
应用程序对游戏手柄上发生的操作做出反应。当按下按钮时,UI上会发生某些事情。但是我遇到了app挂起或java.lang.IllegalStateException:Not on FX application thread异常的问题。
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.
为了解决这个问题我试过以下方法: Platform.runLater()
和任务
用法。但它没有帮助。
In order to fix it I tried the following approaches: Platform.runLater()
and Task
usage. But it didn't help.
以下是问题代码:
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()
模拟游戏手柄按钮活动轮询。当用户按下任何按钮( rnd.nextInt(30)== 3
)时 - UI上会出现一个图像。当用户释放该按钮( rnd.nextInt(30)== 7
)时 - 图像从UI中消失。
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.
如果上面 java.lang.IllegalStateException:不在FX应用程序线程
上发生。如果你将runTask()改为这样:
In case above java.lang.IllegalStateException: Not on FX application thread
occurs. If you change runTask() to something like this:
Platform.runLater(new Runnable() {
@Override
public void run() {
initStubGamepad();
}
});
然后应用程序将挂起,甚至主UI都不会出现,但游戏手柄活动会继续。
Then app will hang or even main UI won't appear at all, but gamepad activity continues.
我想要的只是在游戏手柄上检测到某些活动时显示/隐藏不同的图像(顺便说一句,除了无限循环中的游戏手柄轮询之外,没有办法监控游戏手柄活动)。我错了什么
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
推荐答案
解释
在 第一种情况 中,当您使用时
In the first scenario, when you are using
Task task = new Task<Void>() {
@Override
protected Void call() throws Exception {
initStubGamepad();
return null;
}
}
内部 initStubGamepad()
,正在任务上运行,您正在尝试更新 pressBtn()
和<$ c内的UI组件$ c> releaseBtn()方法,这就是为什么你要面对
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
java.lang.IllegalStateException: Not on FX application thread
因为所有UI更新必须在JavaFX线程上发生
在 第二种情况 中,当您使用时
In the second scenario, when you are using
Platform.runLater(new Runnable() {
@Override
public void run() {
initStubGamepad();
}
});
用户界面没有出现,因为<无限循环在 initStubGamepad()
,它使JavaFX应用程序线程在无限循环上运行
the UI doesnt appear, because you have an infinite loop inside the initStubGamepad()
, which puts the JavaFX application thread run on an infinite loop
解决方案
当你到达这里时,你必须已经找到了解决方案。如果还没有,请尝试将更新Javafx组件放在UI线程上。因此,不要在 Platform.runLater
中调用 initStubGamepad()
,而是尝试调用 pressBtn()
和 releaseBtn()
在其中。
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.
尝试使用
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;
}
}
这篇关于应用程序挂起或“不在FX应用程序线程上”在应用活动期间发生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!