JavaFX ConcurrentModificationException с GridPane.get...Index()

Мне нужно отредактировать содержимое chunkLargeпоэтому я пытаюсь переместить их в дубликат GridPane:

chunkLarge2 = new GridPane();
for (Node n : chunkLarge.getChildren()) {
    chunkLarge2.add(n, GridPane.getColumnIndex(n), GridPane.getRowIndex(n));
}

Это кидает ConcurrentModificationException, Я думаю, что это из-за GridPane.get...Index(n),

Я немного поискал в интернете и нашел несколько вещей. Во-первых, я мог использовать итератор для циклического перемещения по спискам, но я не уверен, как его применить здесь. Следующим было то, что я мог попробовать .getChildrenUnmodified() вместо вашего стандарта .getChildren(), но это только что бросил NoSuchElementException вместо.

Есть идеи?

2 ответа

Решение

ConcurrentModificationException брошен, потому что вы перебираете chunkLargeсписок детей и удаление элементов из него одновременно.

Удаление происходит, когда вы пытаетесь добавить дочерний узел в chunkLarge2 - узел javafx может иметь только одного родителя, поэтому дочерний узел n удаляется из chunkLargeсначала список детей, а затем он добавляется в chunkLarge2Список детей.

Как вы уже сказали, вы можете использовать итератор для решения проблемы:

Iterator<Node> it = chunkLarge.getChildren().iterator();

while (it.hasNext()) {
    // get the next child node
    Node node = it.next();

    int column = GridPane.getColumnIndex(node);
    int row = GridPane.getRowIndex(node);

    // remove method is used to safely remove element from the list          
    it.remove();  

    // node is already removed from chunkLarge, 
    // so you can add it to chunkLarge2 without any problems       
    chunkLarge2.add(node, column, row); 
}

Или без итератора:

// transfer children from chunkLarge to chunkLarge2
chunkLarge2.getChildren().addAll(chunkLarge.getChildren());

// note that you're not iterating over chunkLarge's children list
// (addAll method will make a copy and work with it),
// so it's safe to let the children be automatically deleted

Экземпляр узла может использоваться только как дочерний элемент одного родителя или как корень одной сцены. Если вы добавляете узел в качестве потомка нового родителя, он удаляется из старого родителя. Это означает, что ваш цикл фактически делает то же самое, что и следующий цикл (установка индексов сетки не требуется, поскольку вы хотите сохранить эти индексы):

for (Node n : chunkLarge.getChildren()) {
    chunkLarge.getChildren().remove(n);
    chunkLarge2.getChildren().add(n);
}

Поскольку вы изменяете список, по которому вы перебираете, другими способами, кроме Iterator вы получаете ConcurrentModificationException,

Вам нужно создать новые узлы для второго GridPane для отображения узлов в обоих GridPanes.

Другие вопросы по тегам