0

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.

  • Not everything has to begin with `ui->`. Not local variables. – LogicStuff Feb 26 '17 at 19:24
  • Does your list contain any labels after you run findChildren? – vincent Feb 26 '17 at 19:59
  • Also, it would be helpful to see the dialog code. – vincent Feb 26 '17 at 20:01
  • In the code you added above, you try to reference a string like it is an object (ui->thisString->text()). You can't do that. Strings and variable names are different. – vincent Feb 26 '17 at 20:05
  • @LogicStuff Correct. I've updated based off that recommendation and actually changed where I do still need 'ui' to 'this' instead. – Anthony Rybicki Feb 26 '17 at 20:06
  • @vincent No, findChildren right now is not returning anything, including the labels I am trying to get. I did update the code, so I am not referencing the string as an object anymore. The rest of the dialog code doesn't really relate to this issue (and there's a lot of it - the rest of which runs perfect if I comment this section out). – Anthony Rybicki Feb 26 '17 at 20:10
  • Can you show us where you instantiate some labels? – vincent Feb 26 '17 at 20:10
  • 1
    Are your objects named "mylabel_" exactly? If not you'll need to use a QRegExp, instead of a string: http://doc.qt.io/qt-5/qobject.html#findChildren-1 – vincent Feb 26 '17 at 20:12
  • @vincent They are all instantiated in the .ui file with ''. I'm actually able to accomplish this if I look for all QLineEdits, but not if I specify a group of QLabels as I try to do in the updated example code. – Anthony Rybicki Feb 26 '17 at 20:15
  • I think we need more code. If it works one way, but not the other, there is another problem. – vincent Feb 26 '17 at 20:17
  • What if you replace the string in the findChildren function with QRegExp("mylabel_*")? – vincent Feb 26 '17 at 20:22
  • @vincent Changing from QString to QRegExp solved the problem with my code example. If you make that an answer, I can label it as answered. Thanks. – Anthony Rybicki Feb 26 '17 at 20:23
  • Cool. I've added it. – vincent Feb 26 '17 at 20:31

1 Answers1

1

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;
    ...
};
vincent
  • 1,370
  • 2
  • 13
  • 29
  • Mapping would help if I needed the QLabels mapped for other referencing purposes. However, I just need to pull the text from each of this group of labels. I suspect that findChildren is the method that is best suited for this purpose, but based off the documentation, I'm not certain I am implementing it properly. – Anthony Rybicki Feb 26 '17 at 20:04