Why Layout is reparenting to the top most widget through addChildLayout?
-
Hi I have the following:
QWidget *widget_1 = new QWidget(this); QGridLayout *layout_1 = new QGridLayout; widget_1->setLayout(layout_1); QGridLayout *layout_2 = new QGridLayout; layout_2->addWidget(_qButton, 0, 0, 1, 2, Qt::AlignHCenter); layout_1->addLayout(layout_2,0,1);
So I would expect that layout_1 and _qButton are child of widget_1, meanwhile layout_2 should be child of layout_1.
Here is why: addLayout call adoptLayout that calls
addChildLayout(layout_2) and here we have a l->setParent(this); So layout_2 should be child of layout_1, Since layout_1 has a parent, it callsif (QWidget *mw = parentWidget()) { l->d_func()->reparentChildWidgets(mw); }
that will make _qButton child of widget_1. Where did I go wrong? printing it I have that all are child of widget_1
-
@leonardoMB Layouts are not qwidgets
nor qobjects in generaltherefore they can not be the parent of anything -> the parent responsibility is passed on
Correction: they are indeed QObjects !
-
@J-Hilk but what is with this function so?
void QLayout::addChildLayout(QLayout *l) { if (Q_UNLIKELY(l->parent())) { qWarning("QLayout::addChildLayout: layout \"%ls\" already has a parent", qUtf16Printable(l->objectName())); return; } l->setParent(this); if (QWidget *mw = parentWidget()) { l->d_func()->reparentChildWidgets(mw); } }
This is setting the parent of a lyout to a layout
-
@leonardoMB
thank you for looking up and correcting me :DI was wrong, QLayout has QObject as a base class
https://doc.qt.io/qt-6/qlayout.html and does take ownership and manages lifetime etcmmh,
can you post/explain a bit more of your example case, I don't think I understood it correctly!
-
@J-Hilk No problem, thanks too for helping me.
For sure, I noticed that I forgot one line of code in the question. I edited, sorry:widget_1->setLayout(layout_1); //This will call the following function: void QWidget::setLayout(QLayout *l) //This function will set layout_1 as a child of widget_1
The next step is:
layout_2->addWidget(_qButton, 0, 0, 1, 2, Qt::AlignHCenter); //this one will call QLayout::addWidget void QLayout::addWidget(QWidget *w) { addChildWidget(w); //will call addChildWidget but since layout_2 hasn't parent nothing will change addItem(QLayoutPrivate::createWidgetItem(this, w)); }
In the last line we have:
layout_1->addLayout(layout_2); //that calls addLayout(), that calls QWidget::adoptLayout(QLayout *layout) that calls QWidget::addChildLayout(QLayout * layout)
So, for me this last function QWidget::addChildLayout(QLayout * layout) will reparent the items of layout_2 to widget_1 and will set the parent of layout_2 to layout_1. But it's not what happens, everything becomes child of widget_1 in the end
-
@leonardoMB
thisif (QWidget *mw = parentWidget()) { l->d_func()->reparentChildWidgets(mw); }
is clearly a wrong if condition, I think it evaluates to always true, but that may be compiler dependent.I would blame all strange behaviour on that :DFirst I thought its a copy and past error on your side, but it seems to be in the latest dev branch, If I checked that correctly.
long day.
-
@J-Hilk said in Why Layout is reparenting to the top most widget through addChildLayout?:
is clearly a wrong if condition, I think it evaluates to always true, but that may be compiler dependent.
Sorry, why?
It's just an assign-and-test, so it setsmw
toparentWidget()
. IF THAT IS !=nullptr
it goes intoif
body, if it'snullptr
it does not execute the body. Therefore it will neverreparentChildWidgets(nullptr)
. Is that what you were talking about?
The only compiler-dependency is whether it chooses to issue a warning (not error) message for naked-assignment-within-condition. -
@leonardoMB said in Why Layout is reparenting to the top most widget through addChildLayout?:
What will make _qButton child of widget_1. Where did I go wrong? printing it I have that all are child of widget_1
What will make _qButton child of widget_1?
_qButton = new QPushButton( widget_1 ) or _qButton->setParent( widget_1 ); will make _qButton the child of widget_1.
The layouts of widget_1 can have children of other widgets.