Important: Please read the Qt Code of Conduct -

[solved] QGraphicsScene - clear/delete items

  • Hi,
    I have a QGraphicsScene and buttons on that. I want to delete that buttons, but method clear() doesn't work.


    MainClass::MainClass(QWidget* parent)
    scene = new QGraphicsScene(this);
    QPixMap picture(":/MainClass/Resources/picture.jpg");
    pixmapItem = scene->addPixmap(picture);

    void MainClass::hideButtons();

    Maybe there is a way to do this differently?

    Function hideButtons is invoked by other function (from class MainClass).

    EDIT: ok, I had some mistakes in code, so I now know why it didn't work, but now it crashes every time I try to clear the scene using:


    as same as

    QList<QGraphicsItem*> allGraphicsItems = scene->items();
    for(int i = 0; i < allGraphicsItems.size(); i++)
    QGraphicsItem *graphicItem = allGraphicsItems[i];
    delete graphicItem;
    qDebug()<<"End of hideButtons

    If I comment line with "delete graphicItem" it doesn't crash, but items are not deleting from the scene, because when I tries to readd them, I get:
    "QGraphicsProxyWidget::setWidget: cannot embed widget 0x5f547d8; already embedded
    QGraphicsProxyWidget::setWidget: cannot embed widget 0x5f6a818; already embedded"

    Items, that I remove, don't have parent.
    Interestingly, program crashes after writing "End of hideButtons()", so there must be some method (from beyond my classes) that tries to invoke deleted object.

  • Inspect the call stack when you break in hideButtons(). Is any of the (potentially) deleted object in the call stack?

  • I didn't find if any object was in the call stack, but I think that it could be a problem.
    I think I should do it differently. Maybe someone could suggest how I should do it right.
    I get list of buttons from file (all data like: text, color or size) and create button objects (actually I create pointers to them) . I add them to the scene using


    In some moments I want to remove some of the buttons from scene, but only from scene. I want to have that object on my list of buttons. But when I use

    delete graphicItem;

    that objects are removed from my list (there are pointers on my list but they point to some unknown place of memory - so my objects were probably deleted).

    How I can remove that buttons from the scene without removing them from the scene?

    I know that I can do this with using only scene->removeItem(graphicItem), without using delete graphicItem, but in that case, when I try to add that buttons again to the scene I get

    bq. QGraphicsProxyWidget::setWidget: cannot embed widget 0×5f547d8; already embedded
    QGraphicsProxyWidget::setWidget: cannot embed widget 0×5f6a818; already embedded”

  • After calling
    check what newButton.parent() returns.
    I suspect by calling addWidget, the returned GraphicsProxyWidget becomes the parent of your button.
    You must call delete on the GraphicsProxyWidget, but if the button is a child at that time, it is destroyed as well.

    Try setting a different parent for the button before you destroy the GraphicsProxyWidget.

  • I check parent - there is no parent.
    newButton->parent() returns QObject(0x0), so nothing.

  • If you store your button pointers using QPointer, are the pointers NULL after you remove the items from the scene?

    What object type does newButton have? You could find out more by setting a breakpoint in that object's destructor, and see who actually deletes it.

  • By pointer I mean: ButtonClass *newButton. (ButtonClass inherits QPushButton class).
    But no, the pointers are not NULL, I still can get data from them.

  • Then, I admit, I do not really understand your problem from the information you provided.

  • Ok, maybe I wrote it not so clear.
    I created a class ButtonClass, that inherits QPushButton. Objects of ButtonClass should appear on the scene. I want to have a possibility to remove some of them from the scene (on my request) and after some time to get them back.
    So I have list of this buttons (QList<ButtonClass*> buttonsList), I add them to the scene by invoking method showButtons() created by me. I clicked to other QPushButton (signal clicked() is connected to the slot hideButtons()) to remove them form the scene. Then the function showButton is invoked again, but no buttons is showing up. I get only info:
    QGraphicsProxyWidget::setWidget: cannot embed widget 0×5f547d8; already embedded

  • If all you really want to do is hiding and showing them, then just call hide() and show(), and leave them in the scene.
    Adding and removing items (and especially widgets!) from a scene is a pretty expensive operation.

    If for some reason you really need to remove them from the scene,
    @ scene->removeItem(graphicItem)
    delete graphicItem;
    should do the right thing. If not, describe the effect you see, and we can go from there.

  • If functions hide and show are from QGraphicsScene class?

    EDIT: never mind, I found it. I will try to hide and show. If it will work in a way I don't want. I have only one problem. The functions hide and show refers to QGraphicsItem. If I want to hide or show one button, how can I check which QGraphicsItem is it?

  • When you add the button using addWidget, you get a pointer to a QGraphicsProxyWidget. You can hide and show that using show() and hide(), or setVisible(bool)

  • Ok, thanks, I try to do this in that way

    EDIT: I did it as you adviced me, using QProxyWidget pointer, and I rewrote program to show and hide buttons not delete them everytime.
    After some reflection I decided that better option is to set QGraphicsView as a parent of button and then show and hide it, because it is simplier to change anything related to button.

Log in to reply