Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

find all group boxes in layout



  • Hello,
    I am trying to find the layout attached to a group box, with a specific title, that is inside another layout so I can add a new label that group box's layout.

    TestTab::TestTab(QWidget *parent) : QWidget(parent)
    {
    QVBoxLayout *mainLayout = new QVBoxLayout;    
    QGroupBox *newGrpBox = new QGroupBox("VCM");
    QVBoxLayout *grpLayout = new QVBoxLayout(newGrpBox);
    QLabel *tstLbl = new QLabel("Hello");
    grpLayout->addWidget(tstLbl);
    newGrpBox->setLayout(grpLayout);
    mainLayout->addWidget(newGrpBox);   
    setLayout(mainLayout);
    
    QList<QGroupBox*> childGrps = mainLayout->findChildren<QGroupBox*>();
    foreach(auto obj, childGrps)
    {
        qDebug() << "found group box";
        if(obj->title() == "VCM")
        {
            qDebug() << "Found box with VCM title";
            QList<QVBoxLayout*> grpLay = obj->findChildren<QVBoxLayout*>();
            foreach (auto layOjb, grpLay)
            {
                qDebug() << "Found grp box layout";
                QLabel *newLbl = new QLabel("new lbl");
                layOjb->addWidget(newLbl);
            }
        }
    }
    }
    

    The qDebug statements do not appear from any level for the nested loops indicating that it finds no QGroupBoxes inside the mainLayout. Is there something wrong in my iteration loops? I can't declare the mainLayout to be the parent of the group box on declaration without a compiler error but I thought addWidget takes care of parenting issues and would make the group box a child of that layout. How should I go about accomplishing this task?



  • set object name to each group box and use findChild<QGroupBox *> with object name to find any of them as Jon suggested. Layout is not needed.



  • @thewiggin
    You can do this findChildren() stuff from widgets downward. You are trying to do it from layouts, and that's not how Qt works, parent-child-wise. See e.g. https://stackoverflow.com/questions/4065378/qt-get-children-from-layout

    The layout does not "inject" itself in the parent-child tree, so the widgets stay (direct) children of their parent widget.

    You could use QLayout::count() and QLayout::itemAt() instead.

    Read the comments and answers there for explanation/suggestions.



  • Thank you.

    I can find the layout inside the QGroupBox based off the link you provided:

        QVBoxLayout *vidGrpLay = newGrpBox->findChild<QVBoxLayout*>();
        if(vidGrpLay)
        {
            qDebug() << "Found grp box layout";
            QLabel *newVidGrpLbl = new QLabel("Vid property");
            vidGrpLay->addWidget(newVidGrpLbl);
        }
    

    I am still having trouble understanding how to use count and itemAt to do what I want.

    TestTab::TestTab(QWidget *parent) : QWidget(parent)
    {
    QVBoxLayout *mainLayout = new QVBoxLayout;    
    QGroupBox *newGrpBox = new QGroupBox("VCM");
    QVBoxLayout *grpLayout = new QVBoxLayout(newGrpBox);
    QLabel *tstLbl = new QLabel("Hello");
    grpLayout->addWidget(tstLbl);
    newGrpBox->setLayout(grpLayout);
    mainLayout->addWidget(newGrpBox);   
    setLayout(mainLayout);
        QGroupBox *vidGrp;
        for(int i = 0; i < mainLayout->count(); ++i)
        {
            vidGrp = dynamic_cast<QGroupBox*>(mainLayout->itemAt(i));
            if(vidGrp)
            {
                qDebug() << "Found a group box";
                if(vidGrp->title() == "VCM")
                {
                    qDebug() << "Found VCM group box";
                    QVBoxLayout *vidGrpLay = vidGrp->findChild<QVBoxLayout*>();
                    if(vidGrpLay)
                    {
                        qDebug() << "Found VCM grp box layout";
                        QLabel *newVidGrpLbl = new QLabel("Vid property");
                        vidGrpLay->addWidget(newVidGrpLbl);
                    }
                    break;
                }
                else
                {
                    vidGrp = nullptr;
                }
            }
        }
    }
    

    How do I check if the mainLayout->itemAt(i) is a QGroupBox?



  • @thewiggin said in find all group boxes in layout:

    How do I check if the mainLayout->itemAt(i) is a QGroupBox?

    QGroupBox *gb = qobject_cast<QGroupBox *>(mainLayout->itemAt(i));    // or dynamic_cast<>()
    if (gb)
        qDebug() << "It's a QGroupBox!";
    

    EDIT
    Oh I just saw you have

            vidGrp = dynamic_cast<QGroupBox*>(mainLayout->itemAt(i));
            if(vidGrp)
    

    so that should work?



  • set object name to each group box and use findChild<QGroupBox *> with object name to find any of them as Jon suggested. Layout is not needed.



  • The dynamic cast returns nothing and the qobject_cast throws a compile error:
    testtab.cpp:79: error: no matching function for call to ‘qobject_cast<QGroupBox*>(QLayoutItem*)’
    79 | QGroupBox vidGrp = qobject_cast<QGroupBox>(mainLayout->itemAt(i));
    | ^

    QGroupBox *vidGrp = qobject_cast<QGroupBox*>(mainLayout->itemAt(i));
    


  • @JoeCFD Thanks using find child tied to object name worked

    Not sure why the dynamic cast did not return it or why qobject_cast throws an error but the below snippet works when combined with the other code that has been posted.

        newGrpBox->setObjectName("vidGrpBox");
        QGroupBox *findGp = findChild<QGroupBox*>("vidGrpBox");
        if(findGp)
        {
            QVBoxLayout *vidGrpLay = findGp->findChild<QVBoxLayout*>();
            if(vidGrpLay)
            {
                qDebug() << "Found grp box layout";
                QLabel *newVidGrpLbl = new QLabel("Vid property");
                vidGrpLay->addWidget(newVidGrpLbl);
            }
        }
    

    @JonB Thank you as well!


Log in to reply