[Solved] Deleting QObject that already has a parent



  • In most cases, I am perfectly happy to let a QObject's parent do all the work deleting the object when it's time has come.

    Now I have this "1 %" case where I'm not so happy about it.

    Consider this...
    I have a QGraphicsView inside my main window. The QGraphicsView naturally shows a QGraphicsScene.

    Within the scene is a tree of QGraphicsWidgets (which do NOT have QObject parents, but only QGraphicsItem parents).

    One of the QGraphicsWidgets (in one of my sub-libraries) needs to show a widget. The widget should not appear as a separate window, but should be included in my main window, just on top of my QGraphicsView.

    I solved that in the following way:
    @
    if ( ! scene())
    {
    return;
    }

    if ( scene()->views().size() < 1)
    {
    return;
    }

    QGraphicsView* view = scene()->views()[0];

    if ( ! m_pDataPointSelector )
    {
    m_pDataPointSelector = new CCvui_DataPointSelector();
    }

    m_pDataPointSelector->setParent(view, Qt::FramelessWindowHint);

    m_pDataPointSelector->setGeometry(QRect(QPoint(),view->size()));
    m_pDataPointSelector->show();@

    The widget is where I want it - but only thanks to setting the parent to "view".

    But from a "delete" standpoint, the parent is all wrong: The widget should exist only as long as my QGraphicsWidget exists. However, since it has a parent already, I can't simply delete it in my destructor.

    Because when the application closes, the QGraphicsView is destroyed, which implicitly destroys the QGraphicsScene, which implicitly destroys my QGraphicsWidget - but by the time it's destructor runs, the QGraphicsView has already deleted it's child widgets, and my application crashes.

    Additionally, when my QGraphicsWidget closes and is re-opened, it creates a new widget - but the old one still exists as a child of the QGraphicsView. I would have a resource leak.

    What I am looking for is a way to check whether I am still allowed to delete the widget - or whether it has already been deleted. Or any other good idea to solve my dilemma.



  • The best solution I have found so far is to use the "destroyed()" signal of the widget, in order to track it's destruction. It works, but doesn't seem exactly elegant.


  • Moderators

    You should be able to delete items that are parented. The parenting system is smart enough to remove the deleted item from its list of children.



  • Yes, but the question is: Am I smart enough to know when an item has already been deleted through it's parent? ;)


  • Moderators

    Ah, ok. I understand. Then, yes, you probably want to connect to the destroyed() signal.



  • Ok, it seems connecting to the signal is the best I can do here. Thanks!



  • For QObject derived classes I would recommedn the use of [[Doc:QPointer]]. It does all the housekeeping for you and resets itself to null in case the guarded QObject is deleted.



  • QWeakPointer rather, according to the docs.

    bq. QWeakPointer can be used to track deletion of classes that derive from QObject, even if they are not managed by QSharedPointer. When used in that role, QWeakPointer replaces the older QPointer in all use-cases.

    But the sentence that made me a little unsure was this:

    bq. To obtain the QObject being tracked by QWeakPointer, you must use the QWeakPointer::data() function, but only if you can guarantee that the object cannot get deleted by another context. It should be noted that QPointer had the same constraint, so use of QWeakPointer forces you to consider whether the pointer is still valid.

    What exactly is "context" in this context? Thread context? Doesn't make much sense, as QObjects cannot be used from different threads, anyway (which the following paragraph in the docs point out explicitly). So all I knew was that QWeakPointer does not protect me in some case, and I could not determine whether my case was this case.

    Seemed safer to attach to the destroyed() signal.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.