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

adding widgets to UI on the fly



  • Hi, all -

    Amazingly, I don't think I've ever done this before, and my first effort is not working.

    I need to populate a UI with radio buttons based on the results of a message I receive. I need one radio button for each element in the list I build from the message. (My UI is an empty QDialog.) Here's what I've tried:

    void BootPartition::displayPartitions(QString qsLabels)
    {
        QRadioButton labelButtons[3];
        int x = 100;
        int y = 100;
        int w = 100;
        int h = 20;
    
        QStringList qsl = qsLabels.split(QChar(PART_LABEL_DELIMITER));
        for (int i = 0; i < qsl.size(); ++i)
        {
            labelButtons[i].setText(qsl[i]);
            labelButtons[i].setGeometry(x, y, w, h);
            labelButtons[i].setVisible(true);
            y += 30;
        }
    }
    

    What might I be doing wrong (or not at all)? Thanks.



  • QRadioButton labelButtons[3];

    • it's on the stack so they will be deleted as soon as the function ends
    • you don't add them to a layout/re-parent them so each of them is an independent window as of now
    • you just have a 3 elements array while qsl.size() could be >3
    • to make them work as mutually exclusive you probably also want to add them to a QButtonGroup


  • Thanks, VRonin. It's still early here, so I guess I'm still waking up. Your first two points were the cause of my problem; to your third point, I'll get rid of the magic numbers once I have the essential functionality down.



  • For anyone keeping score at home, here's an updated code snippet. I don't claim it's the ideal way to go, but it works and is (hopefully) easily understood. Not sure my destructor is quite right, so feel free to comment on it.

    void BootPartition::displayPartitions(QString qsLabels, QString qsCurrentLabel)
    {
        QString text;
        QFont font;
        int x = 50;
        int y = 60;
        int w = 200;
        int h = 20;
    
        QStringList qsl = qsLabels.split(QChar(PART_LABEL_DELIMITER));
        for (int i = 0; i < qsl.size(); ++i)
        {
            m_labelButtons.push_back(new QRadioButton(this));
            m_labelButtons[i]->setText(qsl[i]);
            m_labelButtons[i]->setGeometry(x, y, w, h);
            if (m_labelButtons[i]->text() == qsCurrentLabel)
            {
                font = m_labelButtons[i]->font();
                font.setBold(true);
                m_labelButtons[i]->setFont(font);
                text = m_labelButtons[i]->text() + " (current default)";
                m_labelButtons[i]->setText(text);
            }
            m_labelButtons[i]->setVisible(true);
            y += 20;
        }
    }
    ...
    // the below has been changed from the original posting.
    BootPartition::~BootPartition()
    {
        qDeleteAll(m_labelButtons);
        m_labelButtons.clear();
        delete ui;
    }
    

  • Lifetime Qt Champion

    Hi
    what about m_labelButtons.clear() ?
    if you want to delete the pointers in the list.
    Not really needed unless m_labelButtons will try to delete the actual objects pointed to.
    ( if a custom class)


  • Moderators

    hi @mzimmers ,

    first of you gave your RadioButtons a parent, therefore qt's parent/child mechanismn will take care of deleting all children, when the destructor of the main class is called.

    second, this

    for (int i = 0; i < m_labelButtons.size(); ++i)
        {
            m_labelButtons.pop_front();
        }
    

    is a horrible way to clear a Container of its contents, because you don't!
    the m_labelButtons.size() is checked each increment of i and you end up only removing half of all elements!

    If you want to clear the container yourself do it like this:

    for( auto *rBtn : m_labelButtons)
          rBtn->deleteLater();
    m_labelButtons.clear();
    
    //or for the type lazy
    qDeleteAll(m_labelButtons);
    m_labelButtons.clear();
    


  • Hey guys - thanks for the corrections. I've edited my prior post, correcting the destructor.


Log in to reply