I'm writing an evolution simulator application using PyQt4. I have 'creatures' and 'vegetation' on a QGraphics scene. The creatures eat the vegetation, which shrinks as it's eaten, and when it gets down to certain size, it dies and gets deleted from the scene. Creatures that starve also get deleted when they die.
The problem is, when I delete the vegetation items from the scene, I get a segmentation fault (not immediately, it takes varying amount of time). This didn't happen with the creatures, only when I added the vegetation, though they are conceptually the same as the creatures (class instances).
The specific loop where I delete the items is as follows (code is simplified with significant amount of code replaced with comments):
dead = set()
items = self.scene.items()
for item in items:
if isinstance(item, Creature):
# Do some calculation to specify what creature does
for item1 in self.scene.items():
# Look through other items on scene and define interactions
if isinstance(item1, Creature):
# Specify what to do if current item is being compared to another creature
if isinstance(item1, Vegetation):
# Specify what to do if current item is being compared to vegetation
# If creature dies, add to dead set
dead.add(item)
elif isinstance(item, Vegetation):
# Do same as for creature (see above)
# If vegetation dies, add to dead set
dead.add(item)
# Get rid of all dead items from scene
while dead:
deadItem = dead.pop()
self.scene.removeItem(deadItem)
del deadItem
If I comment out the self.scene.removeItem line, then the program doesn't crash.
It seems that the program is calling on a memory address that is no longer valid, but I have no idea what is causing it.
The whole application is quite long, which is why I haven't put it here, but if necessary I can add it.
I'm running Python 3.4.3 using PyQt4 on Windows.
So for anyone who is having similar problems to me, I have found a fix. It is to do with the boundingRect of the vegetation and creatures. When their QRectF() is being changed, the scene still uses the previous boundingRect() before the change. The fix was done by preparing the scene to update the new QRectF() of each item when they change, the code to do so was :
item.prepareGeometryChange()
or
item1.prepareGeometryChange()
depending on which organism had been changed. This line(s) of code was added just before their QRectF() was changed.
Thank you to @strubbly for mentioning about the boundingRect of the items.