Calling setWidget a second time on QDockWidget



  • When I call setWidget on a QDockWidget, I'd expect the QDockWidget to take ownership of that widget. In particular, I'd expect that the widget specified via a previous setWidget call would be deleted on a subsequent setWidget call.

    This is not the behavior of QDockWidget in 5.4.1, and I'm wondering whether this is WAI or a bug. If WAI, what's the rationale for this behavior?

    Thanks!
    Peter



  • The documentation does not state that the QDockWidget takes ownership of the widget set by its setWidget method. If it would be the case it would be stated in the documentation. I will not speculate about the reasons but it can be simply solved by this code:

    //assuming this is something like QMainWindow or some other widget
    QDockWidget *dock = new QDockWidget(this); 
    QWidget *widget1 = new QWidget(dock); //or widget1->setParent(dock);
    dock->setWidget(widget1);
    
    if(dock->widget())
        dock->widget()->deleteLater();
    
    QWidget *widget2 = new QWidget(dock); //or widget2->setParent(dock);
    dock->setWidget(widget2);
    

    You can write a custom class that inherits the QDockWidget and performs this for you inside it (you can then use that instead of QDockWidget and/or promote any QDockWidget to it in the designer if you use it).



  • @Resurr3ction Thanks for the explanation! I thought that widgets taking ownership of children was the norm, even if not explicitly documented. Good to know.


  • Moderators

    @Resurr3ction said:

    If it would be the case it would be stated in the documentation.

    That's not actually true. The fact that ownership is transferred is rarely mentioned in the docs except for the cases it might not be clear(an example). It's the opposite that is always clearly stated - when the ownership is not transferred (an example). If there's nothing in the docs you should assume the ownership is indeed transferred.

    In this particular case the ownership is transferred. You can test it with this small example:

    #include <QApplication>
    #include <QDockWidget>
    #include <QDebug>
    
    struct Test : public QWidget {
      ~Test() { qDebug() << "deleted!"; }
    };
    
    int main(int argc, char *argv[]) {
        QApplication a(argc, argv);
    
        QDockWidget dw;
        dw.show();
    
        dw.setWidget(new Test());
        dw.setWidget(new Test());
    
        return a.exec();
    }
    

    Both instances of Test are correctly deleted by the dock widget's destructor. Note however that setting new widget does not delete previous one immediately. It merely hides it until they are both deleted at the dock's destructor.


Log in to reply
 

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