0

I need to edit the contents of chunkLarge, so I am trying to move them into a duplicate GridPane:

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

This throws a ConcurrentModificationException. I think it's because of GridPane.get...Index(n).

I did a bit of searching online, and found a few things. One was that I could use an Iterator to cycle through lists, but I am unsure how to apply it here. Next was that I could try .getChildrenUnmodified() instead of your standard .getChildren(), but this just threw NoSuchElementException instead.

Any ideas?

Kieee
  • 126
  • 2
  • 15
  • Possible duplicate of [Iterating through a Collection, avoiding ConcurrentModificationException when modifying (removing) in loop](https://stackoverflow.com/questions/223918/iterating-through-a-collection-avoiding-concurrentmodificationexception-when-mo) – Raedwald Oct 17 '18 at 08:29

2 Answers2

2

ConcurrentModificationException is thrown because you're iterating over chunkLarge's children list and deleting elements from it at the same time.

Deletion happens when you try to add a child node to chunkLarge2 - a javafx node can have only one parent, so the child node n is removed from chunkLarge's children list first and then it's added to chunkLarge2's children list.

As you already said, you can use iterator to fix the problem:

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

Or, without iterator:

// 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
Guest 21
  • 672
  • 1
  • 6
  • 10
  • 2
    `GridPane.getColumnIndex(n)` and `GridPane.getRowIndex(n)` won't compile as there is no `n` in your code. When you change `n` to `node`, it might be a problem that you already removed the node... – Holger Oct 14 '18 at 14:38
  • Thank you so much! I forgot all about .addAll(), this will help me so much in more than one occasion! – Kieee Oct 14 '18 at 16:13
0

A node instance can only be used as child of a single parent or as root of a single scene. If you add a node as child of a new parent, it's removed from the old parent. This means your loop effectively does the same as the following loop (setting the grid indices is unnecessary, since you want to keep those indices):

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

Since you're modifying the list you iterate through, by means other than the Iterator you get the ConcurrentModificationException.

You need to create new nodes for the second GridPane to display the nodes in both GridPanes.

fabian
  • 80,457
  • 12
  • 86
  • 114