Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Why Layout is reparenting to the top most widget through addChildLayout?
Forum Updated to NodeBB v4.3 + New Features

Why Layout is reparenting to the top most widget through addChildLayout?

Scheduled Pinned Locked Moved Unsolved General and Desktop
layout
9 Posts 4 Posters 1.7k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    leonardoMB
    wrote on 13 Jun 2022, 03:27 last edited by leonardoMB
    #1

    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 calls

    if (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

    J 1 Reply Last reply 13 Jun 2022, 07:36
    0
    • L leonardoMB
      13 Jun 2022, 03:27

      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 calls

      if (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

      J Offline
      J Offline
      J.Hilk
      Moderators
      wrote on 13 Jun 2022, 07:36 last edited by J.Hilk
      #2

      @leonardoMB Layouts are not qwidgets nor qobjects in general therefore they can not be the parent of anything -> the parent responsibility is passed on


      Correction: they are indeed QObjects !


      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


      Q: What's that?
      A: It's blue light.
      Q: What does it do?
      A: It turns blue.

      L 1 Reply Last reply 13 Jun 2022, 12:07
      1
      • J J.Hilk
        13 Jun 2022, 07:36

        @leonardoMB Layouts are not qwidgets nor qobjects in general therefore they can not be the parent of anything -> the parent responsibility is passed on


        Correction: they are indeed QObjects !

        L Offline
        L Offline
        leonardoMB
        wrote on 13 Jun 2022, 12:07 last edited by
        #3

        @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

        J 1 Reply Last reply 13 Jun 2022, 12:19
        1
        • L leonardoMB
          13 Jun 2022, 12:07

          @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

          J Offline
          J Offline
          J.Hilk
          Moderators
          wrote on 13 Jun 2022, 12:19 last edited by
          #4

          @leonardoMB
          thank you for looking up and correcting me :D

          I was wrong, QLayout has QObject as a base class
          https://doc.qt.io/qt-6/qlayout.html and does take ownership and manages lifetime etc

          mmh,

          can you post/explain a bit more of your example case, I don't think I understood it correctly!


          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          L 1 Reply Last reply 13 Jun 2022, 12:36
          0
          • J J.Hilk
            13 Jun 2022, 12:19

            @leonardoMB
            thank you for looking up and correcting me :D

            I was wrong, QLayout has QObject as a base class
            https://doc.qt.io/qt-6/qlayout.html and does take ownership and manages lifetime etc

            mmh,

            can you post/explain a bit more of your example case, I don't think I understood it correctly!

            L Offline
            L Offline
            leonardoMB
            wrote on 13 Jun 2022, 12:36 last edited by leonardoMB
            #5

            @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

            J 1 Reply Last reply 13 Jun 2022, 13:01
            0
            • L leonardoMB
              13 Jun 2022, 12:36

              @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

              J Offline
              J Offline
              J.Hilk
              Moderators
              wrote on 13 Jun 2022, 13:01 last edited by J.Hilk
              #6

              @leonardoMB
              this

                  if (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 :D

              First 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.


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              J 1 Reply Last reply 13 Jun 2022, 13:42
              1
              • J J.Hilk
                13 Jun 2022, 13:01

                @leonardoMB
                this

                    if (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 :D

                First 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 Offline
                J Offline
                JonB
                wrote on 13 Jun 2022, 13:42 last edited by JonB
                #7

                @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 sets mw to parentWidget(). IF THAT IS != nullptr it goes into if body, if it's nullptr it does not execute the body. Therefore it will never reparentChildWidgets(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.

                L 1 Reply Last reply 14 Jun 2022, 13:53
                1
                • J JonB
                  13 Jun 2022, 13:42

                  @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 sets mw to parentWidget(). IF THAT IS != nullptr it goes into if body, if it's nullptr it does not execute the body. Therefore it will never reparentChildWidgets(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.

                  L Offline
                  L Offline
                  leonardoMB
                  wrote on 14 Jun 2022, 13:53 last edited by
                  #8

                  @JonB So if it's not compile dependent I really didn't understand why I didn't get what I expected

                  1 Reply Last reply
                  0
                  • J Offline
                    J Offline
                    JoeCFD
                    wrote on 14 Jun 2022, 14:03 last edited by
                    #9

                    @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.

                    1 Reply Last reply
                    0

                    7/9

                    13 Jun 2022, 13:42

                    • Login

                    • Login or register to search.
                    7 out of 9
                    • First post
                      7/9
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved