应用挂断或“不在FX应用线程上"在应用活动期间发生 [英] App hangs up or "Not on FX application thread" occurs during app activity

查看:23
本文介绍了应用挂断或“不在FX应用线程上"在应用活动期间发生的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

应用程序对游戏手柄上发生的动作做出反应.当按下按钮时,UI 上会发生一些事情.但我遇到了应用挂起或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()Task 用法.但这没有帮助.

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: Not on FX application thread 发生.如果你把 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() 中,它在 Task 上运行,您试图更新 pressBtn()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();
    }
});

UI 没有出现,因为您在 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应用线程上"在应用活动期间发生的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆