JavaFX : How to get column and row index in gridpane?

I tried to get the row/column index of gridpane, when I click.

I am looking for method like as getSelectedColumn() in JTable(java swing)

I searched this. gridPane.getRowIndex(node)

But it doesn't help to me. Because it need node name to get row/column index.

I make a component of grid by for grammar. So the node name is same. How can I get the value? My partial code is below.

for (int i = 0; i < imageName.length; i++) {
   try {
      img = new Image(getClass().getResourceAsStream(imageName[i]));   
   } catch (Exception e) {
      System.out.println("exception : " + e);
   }
      ImageView imageview = new ImageView(img);
      imageview.setFitWidth(40);
      imageview.setFitHeight(40);

      HBox hbox= new HBox();
      hbox.getChildren().add(imageview);
      tile1.setHgap(40);
      tile1.setVgap(40);
      tile1.add(hbox, i+2, 0);
}

Here's an example about how you could do it if you want only a mouse listener on the gridpane and not on the nodes in the cells. For simplicity I used a Label as cell node, but you can use whatever you prefer.

public class Demo extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(final Stage primaryStage) {

        Pane root = new Pane();

        GridPane gridPane = new GridPane();
        gridPane.setGridLinesVisible(true);

        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {

                Label label = new Label("Label " + i + "/" + j);
                label.setMouseTransparent(true);
                GridPane.setRowIndex(label, i);
                GridPane.setColumnIndex(label, j);

                gridPane.getChildren().add(label);
            }
        }

        root.getChildren().add( gridPane);

        Scene scene = new Scene(root, 400, 300, Color.WHITE);
        primaryStage.setScene(scene);

        primaryStage.show();

        gridPane.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent e) {

                for( Node node: gridPane.getChildren()) {

                    if( node instanceof Label) {
                        if( node.getBoundsInParent().contains(e.getSceneX(),  e.getSceneY())) {
                            System.out.println( "Node: " + node + " at " + GridPane.getRowIndex( node) + "/" + GridPane.getColumnIndex( node));
                        }
                    }
                }
            }
        });

    }

}

You see the clicked cell information in the console.

The same would work if you'd put the listener on the cell node instead of the gridpane, here as a lambda expression:

        label.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> System.out.println( "Node: " + label + " at " + GridPane.getRowIndex( label) + "/" + GridPane.getColumnIndex( label)));

But be aware that the getRowIndex and getColumnIndex methods work only if the data were previously set, as specified in the documentation to these methods.

I have no information about what you intend to achieve, but personally I prefer to work with the nodes themselves instead of some indices in a layout manager which may change.


As @Roland points out, you can also assign a listener to each node. When doing so you can use a single callback method with this approach (mouse-pressed handler as example, but works with others too):

Assigning the handler to the nodes. Let's assume you have an array of buttons:

for (Button button : buttons) {
    button.setOnMousePressed(this::onPress);
}

Mouse pressed handler method:

void onPress(MouseEvent event) {
    int column = GridPane.getColumnIndex((Node) event.getSource());
    int row = GridPane.getRowIndex((Node) event.getSource());
    System.out.println(String.format("Node clicked at: column=%d, row=%d", column, row));
}