JavaFX fireEvent StackOverflowError

时间:2016-12-19 14:09:45

标签: java events javafx javafx-2

我目前正在使用JavaFX开展一个小游戏,我遇到了一些问题,无法捕捉到keyEvents。

现在我可以抓住它们,但程序会抛出一个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); } } 并且按下按键时它没有按照我的预期进行。

这是主要课程:

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();
    } 
}

游戏课程:

gulp.task('size-dest', function() {
    console.log('Total file size in dist folder:');
  return gulp.src(config.dist + '/**/*')
    .pipe(size({showTotal: true, pretty: true}));
});

一些帮助会很棒。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

在场景图中的节点上触发的事件将“冒泡”到父级,然后是父级的父级,最终一直到场景。因此,您在场景中定义的事件处理程序会将事件“重新启动”到root,然后它会冒泡到场景并再次处理,再次被重新激活到root,依此类推......

如果要捕获场景中任何位置的事件,然后在Game类中处理它们,请在Game中定义一些方法来处理事件并调用这些方法。不要“反思”这些事件。

例如:

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);
    }

}