Parent Widget and Child Widget

The constructor of QWidget has an optional parameter:parent. I did not take care about this parameter in the past. Sometimes I create a QWidget  object without providing the parent parameter, as follows.

QWidget *w=new QWidget();

Other times I provide the parent parameter as follows.

QWidget * w=new QWidget(this);

It seems there is not much difference between them until I need to create two separate windows. If I create a QWidget given its parent, I cannot see two separated windows. In fact, the parent-child relationship makes the child widget display in the parent widget and there is only one window to show. If you want the parent widget and the child widget are shown independently, you must not pass the parent parameter when constructing the child widget. This way, the parent-child relationship does not exist between the two widgets. They are both primary window. Alternatively, if you want to show two distinct windows but set up the parent-child relationship in the meanwhile, you can set the flags of the child widget to Qt::Window:

setWindowFlags(Qt::Window);

Now the child widget has its own title bar/maximize/minimize/close button.

Pay attention if you use a layout to contain the child widget.

QVBoxLayout *layout=new QVBoxLayout(this);
Widget *w=new Widget();
layout->addWidget(w);

In the above example, you may think, the layout is the child of the main window, the widget w is the child of the layout, so the widget w is certainly the child of the main window even this is not specified when you create w. Unfortunately, the logic is wrong. Although we add the widget to the layout, we do not create the parent-child relationship between the layout and the widget w. A widget only takes another widget as its parent, which is used to implement the parent/child/owner/owned relationship for underlying native windows system.

The addWidget function will reparent the widget to the widget the layout is installed to, if it is not the same as the widget’s original widget. So even a widget is created without a parent, it still gets its parent when added to a layout. This is why I did not notice the difference between setting and not setting a parent when instancing a QWidget object because I put all child widgets into a layout.

So what is the parenting of QWidget used for?

As we talked before, setting a parent for a widget will make the widget display in its parent unless you change the window flags of the child to Qt::Window.

That explains  the subtle difference between specifying and not specifying a parent when newing a QWidget  object and using a layout.

class Widget:public QWidget
{
public:
    Widget(QWidget *parent=0):QWidget(parent)
    {
        setWindowFlags(Qt::Window);
    }
}

......

QVBoxLayout * layout=new QVBoxLayout(this);
Widget * w=new Widget();
layout->addWidget(w);

 

class Widget:public QWidget
{
public:
    Widget(QWidget *parent=0):QWidget(parent)
    {
        setWindowFlags(Qt::Window);
    }
}

......

QVBoxLayout * layout=new QVBoxLayout(this);
Widget * w=new Widget(this);
layout->addWidget(w);

Can you point out the different effects of the above two code snippets? The first one only shows a single window while the second one displays two windows. Although we set the window flags to Qt::Window in the constructor of Widget, layout->addWidget will reparent w from NULL to the main window in the first code snippet, and the display of w is combined into the main window. In the second code snippet, since we set the parent when creating w, addWidget does not see the change of parent so does not do the reparenting, thus the child widget w will show itself in its own window.

Another effect of parenting is if you delete the parent widget, the child widget will be deleted automatically.  If you close the window of a widget, and the Qt::WA_DeleteOnClose attribute is set for this widget, the widget will be deleted, and all the child widgets of the widget will be deleted too. If all the windows of the primary widgets(i.e. widgets without a parent) are closed, the application will exit even the Qt::WA_DeleteOnClose attribute is not set for these widgets, so all child widgets get closed and deleted too.

 

 

Posted in

Leave a Reply