PDA

View Full Version : Clear a Scene



peace_comp
5th May 2008, 15:32
Hi..
I have a problem to clear a Scene !!
I used the first methode :


void myview::clearScene()
{
QList<QGraphicsItem*> itemsList = scene->items();
QList<QGraphicsItem*>::iterator iter = itemsList.begin();
QList<QGraphicsItem*>::iterator end = itemsList.end();
while(iter != end)
{
QGraphicsItem* item = (*iter);
delete item;
iter++;
}
}
but it doesnt work !!
then I used another methode:

void myview::clear(){
QList<QGraphicsItem*> itemsList = scene->items();
QGraphicsItemGroup *group=scene->createItemGroup(itemsList);
scene->destroyItemGroup(group);
}
this that One stucks the application !!

if someone could help !!
thanks

aamer4yu
6th May 2008, 06:59
You could iterate the items in the scene and call QGraphicsScene::removeItem .
Then you can delete the actual item.

jpn
13th May 2008, 08:36
What do you mean by "doesn't work"? Please, be more exact next time. A QGraphicsItem removes itself from the scene once it gets deleted (as mentioned in destructor docs) so you can just do:


qDeleteAll(scene->items());

Bitto
14th May 2008, 21:35
That's not a good idea; when you delete an item, it will delete all its children, and that list will surely contain pointers to those children as well / since the list is a copy, those pointers will remain after the children are dead. When the loop continues to those (now stale) pointers, the application will surely crash.

Because of this, you must ensure that you only delete toplevel items. Checking if each item in the list returned by items()' parents are null isn't enough; the item may already be dead by the time you dereference the pointer. The items must be copied away first. For example:



QList<QGraphicsItem *> topLevels;
foreach (QGraphicsItem *item, scene->items()) {
if (!item->parentItem())
topLevels << item;
}
qDeleteAll(topLevels);


In Qt 4.4, you can call scene->clear().

http://doc.trolltech.com/4.4/qgraphicsscene.html#clear

wysota
14th May 2008, 22:43
As far as I remember items are placed in this list in such a manner than children are later in the list than their parents, so you could start deleting items starting from the end of the list and be safe. I'm not sure about the order though, so I might be totally wrong. And even if I'm not, the order might change in future releases of Qt, so it's safer to stick with copying top-levels to a separate list. This post is just to suggest a could-be solution and bump my forum post count ;)

BTW. Nice to have you back, Andreas.

Bitto
15th May 2008, 20:54
Actually the plain items() function returns items in no particular order. But in any case even if it did, the returned list would still contain stale pointers to the deleted items :-).

wysota
16th May 2008, 08:26
But in any case even if it did, the returned list would still contain stale pointers to the deleted items :-).

If it did keep that order, you'd be deleting children before their parents, so no extra deletions would have taken place, because while deleting an item, its children would already have been deleted. But since items() doesn't keep that order (maybe it was some other list that kept that order - like qFindChildren() or something) this is all academic talk :)

Bitto
20th May 2008, 18:44
Right you are, haha, if you sort the items by stacking order, the first items in the list will be the topmost ones, which happen to be the deepest descendents. Iterating this list is essentially list a topological sort, so qDeleteAll on this list is safe.

Gah, I didn't think about that! ;-)))