JavaFX fireEvent 堆栈溢出错误

JavaFX fireEvent StackOverflowError

我目前正在使用 JavaFX 开发一个小游戏,但在捕获 keyEvents 时遇到了一些问题。

现在我可以捕捉到它们了,但是程序抛出一个 java.lang.WhosebugError 并且在按下某个键时它没有按照我的预期进行。

这里是主要内容class:

public class WarbladeFX extends Application {

    Game root;

    public void start(Stage primaryStage) {
        root = new Game();
        Scene scene = new Scene(root, 800, 600);
        scene.setFill(new Color(0,0,0,1));


        scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
            public void handle(KeyEvent event) {
                Event.fireEvent(root, event);
            }
        });
        scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
            public void handle(KeyEvent event) {
                Event.fireEvent(root, event);
            }
        });


        primaryStage.setTitle("WarbladeFX");
        primaryStage.setScene(scene);
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }

}

和游戏 class:

public class Game extends Group {

    Entity ship;
    long delta;
    HashSet<String> input = new HashSet<>();

    public Game() {
        File f = new File("src/ressources/ship.gif");
        ship = new Entity(new Image("file:///" + f.getAbsolutePath().replace("\", "/")) ,300, 300);
        getChildren().add(ship);

        setOnKeyPressed(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                //System.out.println(".handle()");
                String code = event.getCode().toString();

                if(!input.contains(code))
                    input.add(code);
            }
        });

        setOnKeyReleased(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                String code = event.getCode().toString();
                input.remove(code);
            }
        });

        new AnimationTimer(){
            @Override
            public void handle(long now) {
                if(input.contains("LEFT"))
                    ship.setVelX(-1);
                if(input.contains("RIGHT"))
                    ship.setVelX(1);

                ship.move(now);
                getChildren().clear();
                getChildren().add(ship);
            }
        }.start();
    } 
}

有些帮助会非常好。

当您在事件处理方法中再次触发该事件时,您将生成一个无限循环。尝试在此方法中处理事件,即对用户输入做出反应。

在场景图中的节点上触发的事件将 "bubble up" 到父级,然后是父级的父级,最终一直到场景。因此,您在场景中定义的事件处理程序 "refire" 到 root 的事件将冒泡到场景并再次处理,再次被重新触发到 root,并且等等...

如果你想捕捉场景中任何地方的事件,然后在Gameclass中处​​理它们,在Game中定义一些方法来处理事件并调用这些方法方法。不要"refire"事件。

例如:

public class Game extends Group {

    Entity ship;
    long delta;
    HashSet<String> input = new HashSet<>();

    public Game() {
        File f = new File("src/ressources/ship.gif");
        ship = new Entity(new Image("file:///" + f.getAbsolutePath().replace("\", "/")) ,300, 300);
        getChildren().add(ship);



        new AnimationTimer(){
            @Override
            public void handle(long now) {
                if(input.contains("LEFT"))
                    ship.setVelX(-1);
                if(input.contains("RIGHT"))
                    ship.setVelX(1);

                ship.move(now);
                getChildren().clear();
                getChildren().add(ship);
            }
        }.start();
    } 

    public void keyDown(String key) {
        if(!input.contains(key))
            input.add(key);    
    }

    public void keyUp(String key) {
        input.remove(code);
    }
}

然后你可以做

public class WarbladeFX extends Application {

    Game root;

    public void start(Stage primaryStage) {
        root = new Game();
        Scene scene = new Scene(root, 800, 600);
        scene.setFill(new Color(0,0,0,1));


        scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
            public void handle(KeyEvent event) {
                game.keyDown(event.getCode().toString());
            }
        });
        scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
            public void handle(KeyEvent event) {
                game.keyUp(event.getCode().toString());
            }
        });


        primaryStage.setTitle("WarbladeFX");
        primaryStage.setScene(scene);
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }

}