Search code examples
c++qtqstringqobject

How to reference an objectName using a QString?


How can someone reference a QObject using a QString? I have tried to accomplish this several different ways based off Qt documentation and similar answers on this site to no avail.

QString string = "mylabel_"
for(int i = 0; i < my.count(); i++)
{
    QString thisString = string + QString::number(i);
    QString labelText = ui->thisString->text();  //'ui' has no members named 'thisString'
    functions::saveLine(&nameFile, labelText);
}

An objectName is just a QString, but using it this way does not work. I have also tried using findChildren, but I might not be understanding the documentation on this function completely.

QList<QWidget *> labels = dialog.findChildren<QWidget *>("mylabel_");
for(int i = 0; i < labels.count(); i++)
{
    QString labelText = ui->labels[i]->text(); //'dialog' has no member named 'labels'
    functions::saveLine(&nameFile, labelText);
}

The end result is, I have a list of QLabels in my dialog that I want to save the text for. I've used the saveLine function elsewhere successfully, but get the above errors trying to reference the object. Any recommendations would be very helpful.

UPDATE: I was able to fix it so that it does not return any errors, but it still does not return any results, so I guess the question is more targeted now at the findChildren method and how the QString translates into an objectName. Here is the updated code, but it still does not return any results.

QList<QLabel *> labels = this->findChildren<QLabel *>("mylabel_");
for(int i = 0; i < labels.count(); i++)
{
    QString labelText = labels.at(i)->text();
    functions::saveLine(&nameFile, labelText);
}

So if I was able to find all of the labels that start with objectName = "mylabel_", and put them into a QList, this would be able to pull the text from them and pass it to the saveLine function I've implemented. However, I don't know why it is not finding the labels based off the QString I put in as the argument for findChildren.


Solution

  • If your objects aren't named "mylabel_" exactly, I don't think that function will work. If you want to find labels based on some regular expression, you'll need to use the QRegExp version of the findChildren function.

    QList<QLabel *> labels = this->findChildren<QLabel *>(QRegExp("mylabel_*"));
    

    That said, you could always use normal c++ to index objects by name. The typical way of doing this is with a map. And it is probably similar to what Qt is doing under the covers. This will be fairly efficient if you have a set known objects of the same type.

    #include <map>
    
    ...
    
    std::map<QString, QLabel*> {
        { "myLabel0", label0 },
        { "myLabel1", label1 },
        { "myLabel2", label2 }
    };
    
    ...
    

    If you're clever, you can even store different types by storing a pointer to a common base class...

    std::map<QString, QObject*> {
        { "myLabel", label },
        { "myWidget", widget },
        { "myButton", button }
    };
    

    Since you're getting the object by name, you can probably remember the type too. From the documentation, it looks like Qt does this, then casts the objects to the type you specify. Upcasting tends to be a little smelly.

    However, if you don't need to store a large number of objects, you could subclass the dialog box, then just store a pointer to the label in a member variable. It is typically a good idea to subclass. This could make your code more reusable.

    class MyDialog : public QDialog
    {
    public:
        ...
        void addLabel(QLabel* label);
        void saveLabelText(QLabel* label);
        ...
    private:
        ...
        QLabel* _myLabel;
        ...
    };