JavaFX - 如何将键盘输入集中在 Hbox 与其他 Pane 中包含的一个 Pane 中

标签 java javafx keyboard eventhandler pane

情况如下图所示: enter image description here

这是一个简单的游戏,我需要使用键盘上的“←”或“→”来移动玩家的砖 block ,但是当我这样做时,应用程序的焦点只是移动到levelPane或infoPane,有什么办法可以明确只允许 gamePane 接收键盘输入,并且只有当我使用鼠标并单击它时,关卡 Pane 才会获得焦点?

Javafx 代码如下:

public void start(Stage primaryStage) throws Exception{
    FXMLLoader loader = new FXMLLoader(getClass().getResource("Game.fxml"));
    Parent page = loader.load();
    Scene scene = new Scene(page);

    Pane levelPane = (Pane)loader.getNamespace().get("levelPane");
    Pane gamePane = (Pane)loader.getNamespace().get("gamePane");
    Pane infoPane = (Pane)loader.getNamespace().get("infoPane");

    Button lv1 = (Button)loader.getNamespace().get("level1");
    Button lv2 = (Button)loader.getNamespace().get("level2");
    Button lv3 = (Button)loader.getNamespace().get("level3");
    Button lv4 = (Button)loader.getNamespace().get("level4");
    Button lv5 = (Button)loader.getNamespace().get("level5");

    Label info = (Label)loader.getNamespace().get("info");


    levelPane.setFocusTraversable(false);
    infoPane.setFocusTraversable(false);
    //gamePane.setFocusTraversable(true);

    gamePane.requestFocus();


    Circle ball = new Circle(10, Color.CADETBLUE);
    ball.relocate(5, 5);

    Rectangle playerBrick = new Rectangle(Data.PLAYER_BRICK_LENGTH,Data.PLAYER_BRICK_WEIGTH,Color.BLACK);
    playerBrick.setArcWidth(20);
    playerBrick.setArcHeight(20);
    playerBrick.setX(150);
    playerBrick.setY(350);

    ArryList<Rectangle> breakableBricks = new ArryList<Rectangle>();



    for (int i = 0; i < Data.BRICK_COUNT ; i++){
        breakableBricks.add(new Rectangle(Data.B_B_LENGTH,Data.B_B_WEIGTH,Color.RED));
        breakableBricks[i].setArcWidth(20);
        breakableBricks[i].setArcHeight(20);
        if(i%5 == 0){
            pixelCountY += Data.B_B_WEIGTH + 10;
        }
        playerBrick.setX(pixelCountX);
        playerBrick.setY(pixelCountY);
        pixelCountX += Data.B_B_LENGTH + 10;
    }

    gamePane.getChildren().add(ball);
    gamePane.getChildren().add(playerBrick);
    gamePane.setBorder(new Border(new BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)));

    gamePane.setOnKeyPressed(new EventHandler<KeyEvent>(){
        @Override
        public void handle(KeyEvent event){
            switch (event.getCode()){               
                case LEFT: goLeft = true;break;
                case RIGHT: goRight = true;break;
            }
        }
    });

    gamePane.setOnKeyReleased(new EventHandler<KeyEvent>(){
        @Override
        public void handle(KeyEvent event){
            switch (event.getCode()){
                case LEFT: goLeft = false;break;
                case RIGHT: goRight = false;break;
            }
        }
    });


    primaryStage.setScene(scene);
    primaryStage.show();    



    Timeline timeline = new Timeline(new KeyFrame(Duration.millis(20),new EventHandler<ActionEvent>() {

        double dx = Data.HORIZONTAL_VELOCITY; //Step on x or velocity
        double dy = Data.VERTICAL_VELOCITY; //Step on y
        double playerBrickSpeed = Data.PLAYER_BRICK_S;//Player Brick moving speed

        @Override
        public void handle(ActionEvent t) {
            //move the ball
            ball.setLayoutX(ball.getLayoutX() + dx);
            ball.setLayoutY(ball.getLayoutY() + dy);

            Bounds bounds = gamePane.getBoundsInLocal();
            Bounds brickB = playerBrick.getLayoutBounds();

            //If the ball reaches the left or right border make the step negative
            if(ball.getLayoutX() <= (bounds.getMinX() + ball.getRadius()) ||
                    ball.getLayoutX() >= (bounds.getMaxX() - ball.getRadius()) ){

                dx = -dx;

            }

            //If the ball reeaches the brick's wall makes the ball bounce
            if(ball.getLayoutY() < brickB.getMaxY() & ball.getLayoutY() > brickB.getMinY()){
                if(ball.getLayoutX() > brickB.getMinX() - Data.HORIZONTAL_VELOCITY & ball.getLayoutX() < brickB.getMinX() + Data.HORIZONTAL_VELOCITY  || ball.getLayoutX() > brickB.getMaxX() - Data.HORIZONTAL_VELOCITY & ball.getLayoutX() < brickB.getMaxX() + Data.HORIZONTAL_VELOCITY ){
                    dx = -dx;
                }
            }

            if(ball.getLayoutX() > brickB.getMinX() & ball.getLayoutX() < brickB.getMaxX()){
                if(ball.getLayoutY() < brickB.getMaxY() + Data.VERTICAL_VELOCITY & ball.getLayoutY() > brickB.getMaxY() - Data.VERTICAL_VELOCITY || ball.getLayoutY() > brickB.getMinY() - Data.VERTICAL_VELOCITY & ball.getLayoutY() < brickB.getMinY() + Data.VERTICAL_VELOCITY){
                    dy = -dy;
                }
            }



            //If the ball reaches the bottom or top border make the step negative
            if((ball.getLayoutY() >= (bounds.getMaxY() - ball.getRadius())) ||
                    (ball.getLayoutY() <= (bounds.getMinY() + ball.getRadius()))){

                dy = -dy;

            }
            //Moving the player's brick
            if(goRight & brickB.getMaxX() < bounds.getMaxX() + Data.PLAYER_BRICK_S & goRight & brickB.getMaxX() < bounds.getMaxX() - Data.PLAYER_BRICK_S){
                playerBrick.setX(playerBrick.getX() + Data.PLAYER_BRICK_S);
            }

            if(goLeft & brickB.getMinX() > bounds.getMinX() + Data.PLAYER_BRICK_S & goLeft & brickB.getMinX() > bounds.getMinX() - Data.PLAYER_BRICK_S){
                playerBrick.setX(playerBrick.getX() - Data.PLAYER_BRICK_S);
            }


        }
    }));
    timeline.setCycleCount(Timeline.INDEFINITE);
    timeline.play();    
}

最佳答案

除非您显示代码,否则没有多大帮助,但我认为您应该使用 GamePane.requestFocus()brick.requestFocus() 来制作 GamePane/brick 监听您的键盘输入。

根据Javadoc for Node 、node.requestFocus()方法

Requests that this Node get the input focus, and that this Node's top-level ancestor become the focused window.

关于JavaFX - 如何将键盘输入集中在 Hbox 与其他 Pane 中包含的一个 Pane 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47671798/

相关文章:

c# - 如何使用 C# 删除(而不是隐藏)Telegram.Bot 中的 ReplyKeyboardMarkup?

Android工具栏SearchView自动打开键盘

java - ActionBarSherlock 中的 SearchView 折叠动画

Javafx 选择多行

java - 如何阻止我的游戏船向后加速?

javafx - 使用 JavaFX 3D 创建坐标网格的最实用方法是什么?

ios - 以编程方式添加文本替换

java - 正确使用单例设计模式

java - 当我尝试在连接时设置它时,将 mysql 中的日期时间和时间戳从默认时区转换为 Java 中的 UTC 不起作用

java - JDBC : How to pass List of object into preparedStatement, 或更好的替代方案