javafx GridPane retrieve specific Cell content

I want to retrieve the content of one specific cell in a Gridpane. I have put buttons in the cells with the

setConstraints(btt , 0 ,1 ) 

setConstraints(btt , 0 ,2 )

getChildren().add....

In my case the GridPane.getChildren.get(10) is not good. I want to go directly to the cell(4,2) and get its content.


Solution 1:

Well I guess if there is no solution to get a specific node from gridpane by is column and row index, I have a function to do that,

private Node getNodeFromGridPane(GridPane gridPane, int col, int row) {
    for (Node node : gridPane.getChildren()) {
        if (GridPane.getColumnIndex(node) == col && GridPane.getRowIndex(node) == row) {
            return node;
        }
    }
    return null;
}

Solution 2:

Assuming you have an 8x8 girdPane where i is the rows and j is the column, you can write:

myGridPane.getChildren().get(i*8+j)

The return type is an object, so you will have to cast it, in my case it's:

(StackPane) (myGridPane.getChildren().get(i*8+j))

Solution 3:

I had some trouble with the presented solution in this question, because the method GridPane.getColumnIndex(Node node) might return null in the first row or colum (when the index is actually 0). Therefore I worked around with the wrapperclass Integer and came to the following solution. Maybe it will help others with the same problem.

private Node getNodeFromGridPane(GridPane gridPane, int col, int row) {
    ObservableList<Node> children = gridPane.getChildren();
    for (Node node : children) {
        Integer columnIndex = GridPane.getColumnIndex(node);
        Integer rowIndex = GridPane.getRowIndex(node);

        if (columnIndex == null)
            columnIndex = 0;
        if (rowIndex == null)
            rowIndex = 0;

        if (columnIndex == col && rowIndex == row) {
            return node;
        }
    }
    return null;
}

Solution 4:

You can add a list that contains every child of the gridpane and each child's parent must have two integers row and column, therefor you'll just have to go through that list and see if it has the right coordinates ! (You should propably add a new class so you can store those coordinates), here is a minimal example of my solution

import java.util.ArrayList;
import java.util.List;

import javafx.scene.Node;
import javafx.scene.layout.GridPane;

public class SpecialGridPane extends GridPane {
    List<NodeParent> list = new ArrayList<>();

    public void addChild(int row, int column, Node node) {
        list.add(new NodeParent(row, column, node));
        setConstraints(node, column, row);
        getChildren().add(node);
    }

    public Node getChild(int row, int column) {
        for (NodeParent node : list) {
            if (node.getRow() == row && node.getColumn() == column)
                return node.getNode();
        }
        return null;
    }
}

class NodeParent {
    private int row;
    private int column;
    private Node node;

    public NodeParent(int row, int column, Node node) {
        this.row = row;
        this.column = column;
        this.node = node;
    }

    public int getRow() {
        return row;
    }

    public int getColumn() {
        return column;
    }

    public Node getNode() {
        return node;
    }
}

Solution 5:

As said in a duplicate, you may have performance issues with the selected answer (getNodeFromGridPane)

Here would be the way to overcome that : https://stackoverflow.com/a/65386693/11284920 But, to sum it up :

1. have a double dimensional array :

private Node[][] gridPaneArray = null;

2. Call a method like so during the initialization of your view :

    private void initializeGridPaneArray()
    {
       this.gridPaneArray = new Node[this.gridModel.getLines() [this.gridModel.getColumns()];
       for(Node node : this.mainPane.getChildren())
       {
          this.gridPaneArray[GridPane.getRowIndex(node)][GridPane.getColumnIndex(node)] = node;
       }
    }

3. Get your node

Node n = this.gridPaneArray[x][y]; // and cast it to any type you want/need