Node.getChildren() problem

Hi I have encountered a weird behavior when trying to get the spatials from a Node:


//Select the file you want to load
Node loaded = (Node) BinaryImporter.getInstance().load(fileChooser.getSelectedFile());

ArrayList<Spatial> allspats = loaded.getChildren();
System.out.println("Size: "+allspats.size()); // 2 (i have 2 boxes in the scene)

for(Spatial x: allspats)
{
   System.out.println("check");
   scene.attachChild(x);
}



And the output is as follows:

Size: 2
check



Sorry, but this makes absolutely no sense to me. It  definitely shows 2 spatials but in the end the loop only does 1 loop? It seems it skips always the last entry of the ArrayList  :?

Hi



The problem is that scene.attachChild indirectly manipulates you "allspats" array. (I have no code in front of me, its like sth with child.removeFromParent() or so).



So your arrayList where you are iterating in your for loop is modified (the first spatial is removed). I am wondering why it wont throw a ConcurrentModificationException or so…



The problem can be solved (i think):


ArrayList<Spatial> allspats = new ArrayList<Spatial>();
allspats.addAll(loaded.getChildren());

for(Spatial s:allspats) scene.attachChild(s);



Regards

Snare

That worked!!!



Thanks man!.. I was pulling my hair out already using different kinds of loops and iterators and converting to array etc.

Great! I am Glad that i could help.



:slight_smile:






In response to owaye's posts in http://www.jmonkeyengine.com/jmeforum/index.php?topic=9560, here is an attempt to explain in more detail what snareoj2 already tried to get across:

snareoj2 said:

The problem is that scene.attachChild indirectly manipulates you "allspats" array. (I have no code in front of me, its like sth with child.removeFromParent() or so).

And yeah, that's exactly what's going on.
Here's owaye's code:
owaye said:


for(Spatial x: allspats)
{
   System.out.println("check");
   scene.attachChild(x);
}




In order to see what's wrong with this, you must rememver that every part of the scenegraph can always have only one parent.
So scene.attachChild(x) removes the child from allspats in order to attach it to an other Node.
That's why allspats.size() gets smaller on each iteration of the for loop.
If that's still hard to grasp, consider that the foreach list iteration shown above essentially boils down to something like this:


int i = 0;
while(i < allspats.size())
{
   Spatial x = allspats.get(i);
   i++;
}


Now it should become obvious that modifying allspats.size() in the loop will change the number of iterations the loop will do.

AAAaaah that's it, now I understand it! Thanks for the detailed explanation :slight_smile:

You're welcome!

I also just noticed that the rather essential i++ was missing from my last code fragment  (://!), but apparently that didn't confuse you too much  :smiley: