Cyprien
Cyprien

Reputation: 1

JavaFX - How to focus keyboard input within one Pane contained in a Hbox with other panes

The situation is described in the following picture : enter image description here

It's a simple game where I need to use "←" or "→" on the keyboard to move the player's brick,however when I do so the application's focus simply moved to the levelPane or the infoPane, is there any way to explicitly allow only the gamePane to receive keyboard input and the level pane will only be focused if I use my mouse and clicked on it?

Javafx code below:

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

Upvotes: 0

Views: 941

Answers (1)

Muzib
Muzib

Reputation: 2581

Can't help much unless you show your code but I think you should use GamePane.requestFocus() or brick.requestFocus() to make the GamePane/brick listen to your keyboard inputs.

According to the Javadoc for Node, the node.requestFocus() method

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

Upvotes: 2

Related Questions