应用程序活动期间应用程序挂起或“不在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; } }