应用程序活动期间应用程序挂起或“不在FX应用程序线程上”

应用程序对游戏手柄上发生的操作做出反应。 当按下按钮时,UI上会发生某些事情。 但我遇到了app挂起或“java.lang.IllegalStateException:Not on FX application thread”exception的问题。

为了解决这个问题,我尝试了以下方法: 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() { @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中消失。

在上面的情况下java.lang.IllegalStateException: Not on FX application thread发生。 如果将runTask()更改为以下内容:

 Platform.runLater(new Runnable() { @Override public void run() { initStubGamepad(); } }); 

然后应用程序将挂起,甚至主UI都不会出现,但游戏手柄活动仍在继续。

我想要的只是在游戏手柄上检测到一些活动时显示/隐藏不同的图像(顺便说一句,除了无限循环中的游戏手柄轮询之外,没有办法监控游戏手柄活动)。 我错了什么

说明

在第一个场景中 ,当您使用时

 Task task = new Task() { @Override protected Void call() throws Exception { initStubGamepad(); return null; } } 

任务上运行的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() ,而是在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; } }