アプリケーションは、ゲームパッドで発生するアクションに反応します。ボタンが押されると、UIで何かが発生します。しかし、アプリがハングアップするか、「java.lang.IllegalStateException:FXアプリケーションスレッドではありません」という例外が発生するという問題が発生しました。
それを修正するために、私は次のアプローチを試みました: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<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から消えます。
上記の場合にjava.lang.IllegalStateException: Not on FX application thread
発生します。runTask()を次のように変更すると、
Platform.runLater(new Runnable() {
@Override
public void run() {
initStubGamepad();
}
});
その後、アプリがハングするか、メインUIがまったく表示されなくなりますが、ゲームパッドのアクティビティは続行されます。
私が欲しいのは、ゲームパッドで何らかのアクティビティが検出されたときに異なる画像を表示/非表示にすることだけです(ところで、ゲームパッドのポーリングを無限ループで監視する以外に、ゲームパッドのアクティビティを監視する方法はありません)。何が悪かった
説明
では最初のシナリオを使用しています、
Task task = new Task<Void>() {
@Override
protected Void call() throws Exception {
initStubGamepad();
return null;
}
}
TaskでinitStubGamepad()
実行されているInside内で、UIコンポーネントとメソッドを更新しようとしているため、pressBtn()
releaseBtn()
java.lang.IllegalStateException: Not on FX application thread
すべてのUI更新はJavaFXスレッドで発生する必要があるため
で2つ目のシナリオは、使用しています、
Platform.runLater(new Runnable() {
@Override
public void run() {
initStubGamepad();
}
});
内に無限ループがあるため、UIは表示されませんinitStubGamepad()
。これにより、JavaFXアプリケーションスレッドが無限ループで実行されます。
解決
ここにたどり着くまでに、あなたはすでに解決策を見つけているはずです。そうでない場合は、Javafxコンポーネントの更新をUIスレッドに配置してみてください。だから、呼び出しの代わりにinitStubGamepad()
内部にPlatform.runLater
、呼び出してみてください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;
}
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加