JavaFX GridPane 检索特定单元格内容

17

我想要检索 Gridpane 中一个特定单元格的内容。我已经将按钮放置在单元格中,并使用了相应的 ID 进行标识。

setConstraints(btt , 0 ,1 ) 

setConstraints(btt , 0 ,2 )

getChildren().add....

在我的情况下,GridPane.getChildren.get(10) 不太好用。我想直接访问单元格(4,2)并获取其内容。


非常感谢您的回复。 - Elias Elias
5个回答

31

如果没有办法通过列和行索引从GridPane中获取特定的节点,我猜我有一个函数可以做到这一点,

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

5
经过这么多年,Java仍然没有提供基本功能,你必须使用这些低效的解决方法来使基本功能正常工作,这真的很奇怪。但我猜这可能是由底层数据结构所致。 - th3penguinwhisperer
确保您的约束已设置。Scenebuilder喜欢将0视为未设置并将字段置为空。因此,请在fxml文件中手动设置约束。例如<Canvas GridPane.columnIndex=”0” GidPan.rowIndex=”0”>。另外,由于无法保证从getRowIndex/getColumnIndex返回非空值,因此应使用Integer对象并在if语句中检查null。例如,if(null != nodeRow && null != nodeCol ... - Olmstov
请问您如何在 label 上实现这个功能? - Mayur Patel

9
假设您有一个8x8的girdPane,其中 i 表示行, j 表示列,您可以编写:

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

返回类型是一个对象,因此您必须进行类型转换,在我的情况下是:

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


3
这在某些情况下可能是正确的,但是子项列表不一定按行/列顺序维护,并且可以在之后通过GridPane.setRowIndex()等方式进行更改... - Adam
我从未使用过setRowIndex(),所以我无法说太多。这个解决方案对我有用,我相信大多数情况下都可以完成工作,只要你不改变默认的行/列索引。 - Ahmad Tn
如果首先特定单元格内没有节点会发生什么? - ihavenoidea
@leandrocoutom 我不确定会发生什么。我现在不使用JavaFX,所以无法确切地告诉你。但它回答了从单元格中检索内容的问题。如果您自己尝试一下,我想知道会发生什么。谢谢。 - Ahmad Tn

3

我在这个问题的解决方案中遇到了一些麻烦,因为方法 GridPane.getColumnIndex(Node node) 可能会在第一行或第一列(当索引实际上是0时)返回null。因此,我使用了包装类Integer进行处理,并得出了以下解决方案。希望对其他遇到同样问题的人有所帮助。

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

2
你可以添加一个列表,其中包含gridpane的每个子项,每个子项的父项必须具有两个整数行和列,因此你只需遍历该列表并查看它是否具有正确的坐标!(你应该添加一个新类,以便可以存储这些坐标),以下是我的解决方案的最小示例。"Original Answer"翻译成"最初的回答"。
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;
    }
}

1

如在一个重复的帖子中所说,您可能会遇到与选定答案(getNodeFromGridPane)有关的性能问题。

以下是克服该问题的方法:https://dev59.com/jGEi5IYBdhLWcg3w7_7P#65386693 但是,总结一下:

1. 使用双维数组:

private Node[][] gridPaneArray = null;

在视图初始化期间调用以下方法:
    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;
       }
    }

获取你的节点。
Node n = this.gridPaneArray[x][y]; // and cast it to any type you want/need

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接