Adding a QWidget to a QGraphicsScene, clearing it, then adding the QWidget again
-
Hello,
here's a code sample:
auto myQGraphicsScene = new QGraphicsScene(); // ... auto myQWidget = new QWidget(); // ... myQGraphicsScene->addWidget(myQWidget); // ... myQGraphicsScene->clear(); // ... myQGraphicsScene->addWidget(myQWidget);
I get a segmentation fault at the last line. What am I missing?
Thanks in advance for your input!
-
Hi,
The graphics scene takes ownership of the widget through theQGraphicsProxyWidget
object returned byQGraphicsScene::addWidget
. When you callQGraphicsScene::clear
the scene deletes all items (including your widget), somyQWidget
becomes a dangling pointer. After that you pass a pointer that references an invalid memory location to theQGraphicsScene::addWidget
and ... voila! you get a segfault. -
Thank you for the reply. To solve this tidily, could you please confirm that the following is efficient:
For every QWidget added to the QGraphicsScene this way:
- Remove it from the QGraphicsScene thanks to
QGraphicsScene::removeItem
. delete
its QGraphicsProxyWidget afterward.
Is anything else required? Do I need to set the QWidget's parent to
nullptr
or anything else before adding it to the QGraphicsScene again? - Remove it from the QGraphicsScene thanks to
-
@Pippin said in Adding a QWidget to a QGraphicsScene, clearing it, then adding the QWidget again:
Is anything else required?
No, this should be just enough.
Do I need to set the QWidget's parent to nullptr or anything else before adding it to the QGraphicsScene again?
Nope, Qt should have done that for you when you removed the item from the scene.
-
@kshegunov said in Adding a QWidget to a QGraphicsScene, clearing it, then adding the QWidget again:
Nope, Qt should have done that for you when you removed the item from the scene.
Well technically I didn't remove the QWidget, but its QGraphicsProxyWidget. At this point, both QWidget's and QGraphicsProxyWidget's parent is
nullptr
then, correct? -
@Pippin said in Adding a QWidget to a QGraphicsScene, clearing it, then adding the QWidget again:
Well technically I didn't remove the QWidget, but its QGraphicsProxyWidget. At this point, both QWidget's and QGraphicsProxyWidget's parent is nullptr then, correct?
I can't say for sure without actually testing it out, but you should get a
QWidget
that has a parentQGraphicsProxyWidget
. Whereas theQGraphicsProxyWidget
should have no parent. -
@kshegunov So this is the function I've been using:
void freeWidget(QWidget* foo) { const auto proxy = foo->graphicsProxyWidget(); myClass::myStaticQGraphicsScene->removeItem(proxy); foo->setParent(nullptr); delete proxy; }
But even after that, when I add the QWidget again to
myClass::myStaticQGraphicsScene
, I get a segmentation fault. Sometimes the following message is printed shorty before:QGraphicsProxyWidget::setWidget: cannot embed widget 0x247f680; already embedded
Any insight?
-
I apologize but I'd like to bump this. Is there a way to set a Widget's QGraphicsProxyWidget to
nullptr
as well? Clearly what I'm doing isn't enough.Solved: Indeed I had to set the Widget's QGraphicsProxyWidget to
nullptr
but the tricky part is, you can only do that from the QGraphicsProxyWidget, not from the QWidget. Here's the fixedfreeWidget
function:void freeWidget(QWidget* foo) { const auto proxy = foo->graphicsProxyWidget(); myClass::myStaticQGraphicsScene->removeItem(proxy); proxy->setWidget(nullptr); foo->setParent(nullptr); delete proxy; }
Thanks again @kshegunov for your help yesterday.
(Edit: it seems that
foo->setParent(nullptr);
is useless.) -
Thanks for posting the solution.
@Pippin said in Adding a QWidget to a QGraphicsScene, clearing it, then adding the QWidget again:
it seems that foo->setParent(nullptr); is useles
proxy->setWidget(nullptr);
will set the widget's parent to null for you, yes.
-
-