JavaFX点击GridPane获取ImageView行列索引返回null如何解决
问题根源
你犯了两个核心错误:
- 点击事件绑定对象错误:你把点击监听绑在了
gameGrid容器本身,event.getSource()拿到的是GridPane实例,而GridPane.getColumnIndex()、GridPane.getRowIndex()是用来查询GridPane的子节点的行列属性的,容器本身没有该属性,所以必然返回null。 - 类型拆箱风险:这两个方法返回的是*
Integer包装类型*,你直接用基础类型int接收,一旦返回null就会触发自动拆箱空指针异常。
解决方案
这里提供两种可行方案,按需选择即可:
方案1:给每个ImageView子节点单独绑定点击事件(更推荐)
逻辑简单性能好,你只需要在创建ImageView并添加到GridPane的时候,给每个子节点单独加监听即可:
// 你原来初始化单元格ImageView的逻辑 ImageView cellImg = new ImageView(); int col = 0; // 你要设置的列号 int row = 0; // 你要设置的行号 GridPane.setColumnIndex(cellImg, col); GridPane.setRowIndex(cellImg, row); gameGrid.getChildren().add(cellImg); // 给单个单元格绑定点击事件 cellImg.setOnMouseClicked(event -> { Node source = (Node) event.getSource(); Integer colIndex = GridPane.getColumnIndex(source); Integer rowIndex = GridPane.getRowIndex(source); // 先判空避免空指针 if (colIndex == null || rowIndex == null) return; if(event.getButton() == MouseButton.PRIMARY) { game.newRevealCell(colIndex, rowIndex); } else if(event.getButton() == MouseButton.SECONDARY) { game.getGrid()[colIndex][rowIndex].setFlagged(true); } });
方案2:保持GridPane全局绑定,通过拾取结果获取子节点
如果你确实需要把事件统一绑在GridPane上,可以通过鼠标事件的拾取结果拿到实际被点击的节点,向上遍历找到GridPane的直接子节点后再取索引:
gameGrid.setOnMouseClicked(event -> { // 获取实际被点击的节点 Node clickedNode = event.getPickResult().getIntersectedNode(); // 向上遍历直到找到GridPane的直接子节点 while (clickedNode != null && clickedNode.getParent() != gameGrid) { clickedNode = clickedNode.getParent(); } if (clickedNode == null) return; Integer colIndex = GridPane.getColumnIndex(clickedNode); Integer rowIndex = GridPane.getRowIndex(clickedNode); if (colIndex == null || rowIndex == null) return; // 业务逻辑和之前一致 if(event.getButton() == MouseButton.PRIMARY) { game.newRevealCell(colIndex, rowIndex); } else if(event.getButton() == MouseButton.SECONDARY) { game.getGrid()[colIndex][rowIndex].setFlagged(true); } });
内容的提问来源于stack exchange,提问作者NaturalBottle
相关产品推荐
相关产品推荐

