0

I'm working on a simple board game implementation in JavaFX8.

For the game board, my decision was to use a 10x10 GridPane and fill it's cells with Rectangles in form's initialize method.

private void drawBoard() {
    gridpaneBoard.getChildren().clear();
    for (int y = 0; y < gridpaneBoard.getRowConstraints().size(); y++)
        for (int x = 0; x < gridpaneBoard.getColumnConstraints().size(); x++) {
            Rectangle rect = new Rectangle(55,55);
            rect.setStroke(Color.BLACK);

            Tile tile = GameController.getInstance().getBoard().getTile(x, y);
            if (tile.hasBranch())
                rect.setFill(QuestionDifficulty.values()[tile.getBranch()
                                                         .getQuestion().getQuestion()
                                                         .getLevel()].getColor());
            else
                rect.setFill(Color.WHITE);

            gridpaneBoard.add(rect, x, y);
            gridpaneBoard.add(new Label(String.valueOf(tile.getNumber())), x, y);
        }
}

In order to animate player token movement after dice rolls, I figured I need to know the center x & center y of each tile (to create a path transition from source tile to destination tile).

I've tried all sorts of answers given to other people's questions, but everything returned 0,0 for me.

This is the container hierarchy in this scene:

container hierarchy

This is how the output looks at the moment:

enter image description here

If GridPane is fine for what I'm trying to achieve, how can I get a child's (in this case a rectangle's) screen / scene center x,y?

If GridPane is not fine, can you point me to alternatives and how I can achieve what I want then..

Thank you!

Igal Klebanov
  • 348
  • 2
  • 15
  • 1
    You need to know the centerX and centerY to center the Label inside your rec ? – Bo Halim Dec 02 '16 at 11:30
  • that could be another use for my question. but my main concern is finding center of rectangle for path transitions. for example.. move player token from tile #4 to tile #12. (animation will also have #5, #6, #7, #8, #9, #10, #11 in the path) – Igal Klebanov Dec 02 '16 at 11:31
  • have solved the label alignment issue with simply running on row / column constraints and setting V / H alignment to V / H pos.CENTER. – Igal Klebanov Dec 02 '16 at 11:44

2 Answers2

2

You can simply call getBoundsInParent to get the dimensions of the Node in it's parent.

The following example is a bit simplified, but it should demonstrate the approach nonetheless:

@Override
public void start(Stage primaryStage) {
    GridPane gridpaneBoard = new GridPane();
    for (int y = 0; y < 10; y++) {
        for (int x = 0; x < 10; x++) {
            Rectangle rect = new Rectangle(55, 55);
            rect.setStroke(Color.BLACK);

            rect.setFill((x + y) % 2 == 0 ? Color.WHITE : Color.DARKGRAY);

            gridpaneBoard.add(rect, x, y);
        }
    }

    gridpaneBoard.setOnMouseClicked(evt -> {
        Node target = evt.getPickResult().getIntersectedNode();

        if (target != gridpaneBoard) {
            // in your case you'd need to make sure this is not the Label
            Bounds bounds = target.getBoundsInParent();
            System.out.println("bounds = " +bounds);
            System.out.println("centerX = " +(bounds.getMinX() + bounds.getWidth()/2));
            System.out.println("centerY = " +(bounds.getMinY() + bounds.getHeight()/2));
        }
    });

    Scene scene = new Scene(gridpaneBoard);

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

If coordinates different to the GridPane coordinates are required, you could use getBoundsInLocal in combination with localTo... instead:

Bounds bounds = target.localToScene(target.getBoundsInLocal());

for scene bounds or

Bounds bounds = target.localToScreen(target.getBoundsInLocal());

for screen bounds.

Note: This works independent from any properties modifying how GridPane layouts it's children.

fabian
  • 80,457
  • 12
  • 86
  • 114
  • have tried this: http://paste.ofcode.org/kpkcc2gSbagTbL8zWevtQ6 and all rectangles returned 27.5 on center x,y. – Igal Klebanov Dec 02 '16 at 16:25
  • 1
    @ckid You probably invoke that code before the first layout pass. In this case `GridPane` has not yet set the position of it's children. If called later on a input event for the ui, there should be no such problem. E.g. this is what my code prints, if you click on the bottom right rect: `bounds = BoundingBox [minX:504.0, minY:504.0, minZ:0.0, width:56.0, height:56.0, depth:0.0, maxX:560.0, maxY:560.0, maxZ:0.0] centerX = 532.0 centerY = 532.0` – fabian Dec 02 '16 at 16:47
  • that's right, I did the syso's in initialize, right after drawBoard().. tested same code on the action event for Roll button and it gives me, what seems to be expected results! thanks! – Igal Klebanov Dec 02 '16 at 17:03
1

You can use :

-GridPane.getColumnIndex(Node) to get the column index.

-GridPane.getRowIndex(Node) to get the row index.

-Since you know the Width and the Height (55,55) of your child (Rectangle) you can just calculate its centerX, centerY which is relative to its position in the container, but since you use a GridPane I don't think it is possible since this one has Constraints. You can fix it by changing the container of your object or completely redraw it inside another raw/column, here is an example Replace a node at (row,col).

Community
  • 1
  • 1
Bo Halim
  • 1,716
  • 2
  • 17
  • 23
  • Is there a way to get the GridPane's top left corner x,y scene position? I'll probably be able to get each tile's scene center based on that (and knowing their width / height and number of columns / rows). – Igal Klebanov Dec 02 '16 at 12:49
  • 1
    why don't you use a TilePane ? – Bo Halim Dec 02 '16 at 13:07
  • tried TilePane right now. As far as I can tell, it doesn't allow adding more than 1 node to a single position. Is getting screen / scene x,y of children possible or easier with TilePane? – Igal Klebanov Dec 02 '16 at 13:22
  • problem with 1 node per position solved with adding StackPane with Rectangle and Text instead of just the Rectangle. – Igal Klebanov Dec 02 '16 at 13:33