Donotalo
Donotalo

Reputation: 13035

How to delete all QGraphicsItem from QGraphicsScene

I've written a derived class from QGraphicsScene. At a point I need to remove all items from the scene and I want the items to be physically destroyed (destructor called). I tried the following:

QList<QGraphicsItem*> all = items();
for (int i = 0; i < all.size(); i++)
{
    QGraphicsItem *gi = all[i];
    removeItem(gi);
    delete gi; // warning at this line
}

Qt Creator emits a warning: warning: C4150: deletion of pointer to incomplete type 'QGraphicsItem'; no destructor called

I'm not sure why is that. QGraphicsItem has virtual destructor so the items should be deleted from memory.

If this is not the right way, how can I delete all QGraphicsItems from QGraphicsScene? Note that I know when the scene is deleted, all items will also be deleted. But i want to remove items from scene and draw other items. I want the removed items to be deleted from memory.

Upvotes: 11

Views: 18601

Answers (3)

alexisdm
alexisdm

Reputation: 29896

You can remove and delete all items with QGraphicsScene::clear().

Upvotes: 19

Stephen Chu
Stephen Chu

Reputation: 12832

Like jpalecek pointed out, you are missing the header file. You should accept his answer. I am just going to point out two potential issues:

First of all, you don't need to call QGraphicsScene::removeItem(). QGraphicsItem::~QGraphicsItem() does that for you.

Secondly. Be careful if you put any QGraphicsItem inside of others. That is, you have items that are children of other items. The destructor of QGraphicsItem automatically delete all its children. So when you loop through the items returned from QGraphicsScene, you may end up deleting a child item that has already been deleted by its parent. For example, say you have 2 items, A and B, and B is a child of A. When you delete A, B is deleted automatically. And then you get to B and try to delete it. BOOM!

A safer way to do this is to test if the item is the top level one, i.e. it has no parent:

QList<QGraphicsItem*> all = items();
for (int i = 0; i < all.size(); i++)
{
    QGraphicsItem *gi = all[i];
    if(gi->parentItem()==NULL) {
        delete gi;
    }
}

Upvotes: 12

jpalecek
jpalecek

Reputation: 47770

You have to

#include <QGraphicsItem>

in that file. Otherwise, the compiler doesn't know what QGraphicsItem is, that it has a virtual destructor, etc.

Upvotes: 8

Related Questions