javafx GridPane retrieve specific Cell content
Asked Answered
S

5

17

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.

Sulk answered 18/12, 2013 at 10:4 Comment(0)
K
31

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;
}
Keeley answered 18/12, 2013 at 11:26 Comment(3)
It's extremely weird that after all those years java doesn't provide basic functionality and you have to use these kind of inefficiënt workarounds to make basic stuff work. But I guess it's the underlying datastructure that's at the base.Plasia
Make sure your constraints are set. Scenebuilder likes to treat 0 as not set and nulls the field. So manually set the constraints in the fxml file. e.g <Canvas GridPane.columnIndex=”0” GidPan.rowIndex=”0”>. Also since it's not guaranteed to return a non-null value from getRowIndex/getColumnIndex you should use an Integer object and check for null in the if statement. e.g. if(null != nodeRow && null != nodeCol ...Multi
Can you please tell me how to implement this for a label ?Entwine
J
11

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))

Jenness answered 27/12, 2016 at 16:0 Comment(4)
This may be true in some cases but children list isn't necessarily maintained in order of row/column and may be altered later with GridPane.setRowIndex() etc...Luxuriant
I never used setRowIndex() so I can't say much. This solution worked for me and I believe should get the job done most of the times, when you don't alter the default row/column indexes.Jenness
What happens if there is not a node inside the specific cell in the first place?Intoxicative
@leandrocoutom I'm not sure what happens. I'm not working with javafx nowadays so I can't really tell. But it answers the question to retrieve content from the cell. If you try it out yourself, I'd like to know what happens. ThanksJenness
M
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;
}
Magnify answered 1/9, 2020 at 10:4 Comment(0)
M
2

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;
    }
}
Microfarad answered 26/3, 2019 at 23:44 Comment(0)
M
1

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

Here would be the way to overcome that : https://mcmap.net/q/456763/-javafx-get-node-by-row-and-column 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
Mame answered 21/12, 2020 at 2:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.