JavaFX国际象棋棋子移动报错:ConcurrentModificationException原因排查
解决JavaFX移动棋子时的ConcurrentModificationException问题
这个ConcurrentModificationException我在JavaFX开发里也碰到过,根源很简单:你在遍历GridPane的子节点列表的同时,直接修改了这个列表的结构(调用gridPane.getChildren().remove(node))。
Java的集合迭代器有个「快速失败」机制:当迭代器正在遍历集合时,如果集合被迭代器之外的操作修改了(比如直接调用集合的remove/add方法),迭代器就会抛出这个异常来阻止潜在的错误行为。你用的增强for循环底层依赖的就是迭代器,所以在循环里删元素肯定会触发这个问题。
怎么修复?
给你两种靠谱的解决方案:
方案1:使用迭代器的remove()方法替换直接删除
迭代器自己的remove()方法会同步更新迭代器的内部状态,不会触发并发修改检测:
public void MovePawn(GridPane gridPane, int col, int row) { int co = 0; // 用来跳过棋盘上方的第一个匹配节点 Iterator<Node> iterator = gridPane.getChildren().iterator(); while (iterator.hasNext()) { Node node = iterator.next(); if (GridPane.getColumnIndex(node) == col && GridPane.getRowIndex(node) == row) { if (co == 1) { // 用迭代器的remove方法删除,安全不抛异常 iterator.remove(); gridPane.add(this.IMG, this.x, this.y + 2); } co = 1; } } }
方案2:先收集要删除的节点,遍历完成后再统一处理
这种方式更直观,尤其适合需要批量删除的场景,先把要删的节点记下来,等遍历完再操作集合:
public void MovePawn(GridPane gridPane, int col, int row) { int co = 0; Node targetNode = null; // 存储要删除的目标节点 // 先遍历,只收集目标,不修改集合 for (Node node : gridPane.getChildren()) { if (GridPane.getColumnIndex(node) == col && GridPane.getRowIndex(node) == row) { if (co == 1) { targetNode = node; } co = 1; } } // 遍历结束后再修改集合 if (targetNode != null) { gridPane.getChildren().remove(targetNode); gridPane.add(this.IMG, this.x, this.y + 2); } }
额外提一句
你的co变量逻辑是为了跳过棋盘上方的第一个匹配节点对吧?这个思路没问题,但要确保计数逻辑和你的UI层级对应,避免误删或者漏处理节点哦。
内容的提问来源于stack exchange,提问作者xCrazy
相关产品推荐
相关产品推荐

