list of labels not returning values as expected



  • Hello!

    I'm having trouble extracting the data I'd like out of a list of QLabels.

    I defined my list in my header as such
    QList<QLabel*> myListOfLabels;and access it from two functions in my .cpp file.

    One file adds to the list and checks to see that it is indeed the text I wanted.

     myListofLabels.push_back(someQlabel);
     qDebug() << myListofLabels.at(0); //not necessarily at index 0, could be iterated over.
    

    and the other is supposed to print the text of the label. This should be the same as qDebug() << myListOfLabels.at(0); but it prints a null value. I can check in this function if there is anything in the list and it does returns the value I expect.

    How can I get the values to print to qDebug() in the second function?


  • Qt Champions 2016

    Hi
    Your list is
    QList<QLabel*>

    so
    qDebug() << myListofLabels.at(0);
    prints the address ?

    qDebug() << myListofLabels.at(0)->text();
    should print the text.



  • @mrjj
    Thank you for your response!

    So when I do qDebug() << myListofLabels.at(0);, I get QObject(0x7fb3d55193c0), which is the address.
    I was expecting a QLabel returned but I got a QObject, which I understand since it is the top most parent of QLabel.
    So I tried qDebug() << myListofLabels.at(0)->text() and i get the null value.

    I tried qobject_cast<QLabel*>(myListofLabels.at(0))->text(); and my app crashes.



  • Hi @mar0029
    This sample code may help you.
    Widget::Widget(QWidget *parent)
    : QWidget(parent)
    {
    hlayout = new QHBoxLayout(this);
    for(int i=0;i<7;i++){
    QString str = QString::number(i);
    QLabel *lb = new QLabel(str);
    lb->setObjectName(str);
    hlayout->addWidget(lb);
    myListofLabels.append(lb);
    }
    }

    void Widget:: Print_labelName(){
    QLabel *lb_test;
    for(int i=0;i<myListofLabels.length();i++){
    lb_test = myListofLabels.at(i);
    qDebug()<<"label ["<<i<<"] ::"<<lb_test->text()<<endl;
    }
    }

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    Widget w;
    w.show();

    w.Print_labelName();
    
    return a.exec();
    

    }



  • @yuvaram , thank you for the response!

    I tried something similar to your void Widget::Print_labelName() function but it still returns the null value.

    Question: I am using finding and adding the QLabel I want from a layout using the following:
    checkBoxLabels.append(qobject_cast<QLabel*>(layoutsFromtab0.at(i)->itemAt(j+1)->widget()));
    I wanted to make sure that the labels were of the correct type, even though I cast them as such, with qDebug() << checkBoxLabels.at(0)->metaObject()->className(); and it returns QLabel as expected.

    When the QDialog from which this function is called is closed, what happens to the list of labels where I added all of my labels? I declared the list in the header, so as to have access to it later, but I fear something else is happening when the QDialog goes away.

    Thank you for your time.


  • Qt Champions 2016

    @mar0029 said:

    checkBoxLabels.append(qobject_cast<QLabel*>(layoutsFromtab0.at(i)->itemAt(j+1)->widget()));

    If this find an object that is not a QLabel, it will insert NULL..
    and if u ever say NULL->text() u will crash.



  • @mrjj , thank you for your response!!

    That is good to know that if i call NULL->text() that my app will crash.

    By calling checkBoxLabel.at(0)->metaObject()->className(); I know that there is an object there but when i call checkBoxLabel.at(0)->text(); it returns a null value. Why wouldn't the value stay the same?


  • Qt Champions 2016

    @mar0029
    Well its hard to say what is going on.
    They dont normally loose their text.

    If you do
    QLabel *test=checkBoxLabel.at(0);
    test->setText("HELLO");
    does sit change them?

    also
    if
    QList<QLabel*> myListOfLabels
    lives in dialog
    and you close/delete dialog. List is invalid.



  • @mrjj

    The QList was defined in the header as:

     Private:
          QList<QLabel*> checkBoxLabels;
    

    When I do test->setText("hello"); , it does change the value for each value in the QList.

    EDIT:
    I was reading about passing objects in and out of dialogs using signals but I'm not quite sure how that works.


  • Qt Champions 2016

    @mar0029
    Hi if you can setText then list is ok ?
    So what part is not working?
    if myListOfLabels is a class member, then you can use from
    any function in that class.
    so in what function does it stop working?

    Very short with signals.
    http://doc.qt.io/qt-5/signalsandslots.html
    you can define a signal

    void MyFatListReady( QStringList list);

    and you can then
    QStringList real_list;
    (build the list)
    emit MyFatListReady(real_list);

    Then from say mainwindow, you can connect this signal to a slot
    and in that slot use the list.



  • @mrjj
    Thank you for your response.
    What isn't working is this: the text that I set to the labels the first time I opened the dialog goes to NULL. Using myListOfLabels->count(); on the second time opening the dialog, provides the suspected number of items.


  • Qt Champions 2016

    @mar0029
    Well, how do u set text?
    In dialog constructor?
    Why is second time different?
    When do u add to list?
    how do you close dialog ?

    U must do something I dont expect with the list. else it must just work.
    So please show most code else its impossible to guess.



  • @mrjj

    Ok. Here is some code. I tried to change as little as possible.

     void MainWindow::configFunction()
     {
    configScreen = new QDialog;
    configScreen->setFixedSize(575,500);
    
    myHbox = new QHBoxLayout;
    
    tab0 = new QWidget;
    tab1 = new QWidget;
    tab2 = new QWidget;
    tab3 = new QWidget;
    
    sa0 = new QScrollArea;
    sa1 = new QScrollArea;
    sa2 = new QScrollArea;
    sa3 = new QScrollArea;
    
    vbox0 = new QVBoxLayout;
    vbox1 = new QVBoxLayout;
    vbox2 = new QVBoxLayout;
    vbox3 = new QVBoxLayout;
    
    configTabArea = new QTabWidget;
    configMainVbox = new QVBoxLayout;
    
    configTabArea->setObjectName("configTabArea")
    
     //Get locations of the files to pull variables from
    QFile file(setupLocation);
    
    file.open(QIODevice::ReadOnly);
    QTextStream in(&file);
    
    while(!in.atEnd()) //gets contents of file into queue
    {
        inQueue.enqueue(in.readLine()); // this queue holds all of the file locations that i'll pull from later. 
    }
    file.close();
    
    for(int i = 1; i < inQueue.size(); i++)//checks to see if there is anything after equals sign of file1_location =
    {
        if(inQueue.at(i).length() > 18) 
        {
            qDebug() << "length is > 18";
            QChar mychar = Qt::Key_Slash;
            QString string = inQueue.at(i);
            int slashLocation, j;
            j = 0; slashLocation = 0;
    
            while((j = string.indexOf("/", j)) != -1)
            {
                if(string.at(j) == mychar)
                {
                    slashLocation = j;
                    break;
                }
                ++j;
            }
            activeFile = (string.right(string.length() - slashLocation));
            outQueue.enqueue(activeFile);
        }
    }
    
    //get file1 variables
    QFile file1(outQueue.at(0));
    QFile file2(outQueue.at(1));
    QFile file3(outQueue.at(2));
     //    QFile file4(outQueue.at(3)); // place holder for future
    
    QQueue<QString> varNameQ;
    QQueue<QString> varQ;
    QQueue<QString> commentQ;
    QQueue<qint32> orderQ;
    QQueue<QString> boldString;
    
    qint8 zero = 0;   qint8 one = 1; qint8 three = 3; qint8 four = 4; //these will be the variables in the orderQ.
    //header #      //varName #    //varQ #       //comment #      //newLine #
    
    QString stringFromInput;     //this will hold an entire line from the "in" textStream.
    QString headerString;       // this is a special case in that there is only one of these.
    //QStringList myStringList;   // since Qt doesn't support the getline function that makes file parsing more intuitive in c++,
                                // it is necessary to break up the 'stringfromInput into chunks that make since
                    // UPDATE To myStringList:: I used QString::left(), mid(), right() to get substrings of the string. this
                    // let me keep the original. using these functions, logic, and math, i was able to simplify the process.
    
    QString varName; QString var; QString comment; /*qint32 newLine = 0;*/
    QString nullString = "";
    
    QTextStream in_0(&file1);  // this is similar to std::fstream, the ifstream portion. the ofstream portion comes in MainWindow::saveFunction
    QTextStream in_1(&file2);
    QTextStream in_2(&file3);
     //    QTextStream in_3(&file4); //place holder for future input stream for sacsap
    
    
     //START file1 STUFF
    if(file1.size() == 0)
    {
        qDebug() << "The file is empty";
    }
    else if(file1.size() != 0 && file1.open(QIODevice::ReadOnly))
    {
        qDebug() << "file1 Parse";
        bool firstCheck = true;
        while(!in_0.atEnd())   //while the file is available to be read AND it is not at the end yet
        {
            //
           //Add stuff to the queues that hold the variables, variable names, comments
          //
        qDebug() << "size of checkedLabelstab0 is " << checkedLabelstab0.count();
     //checkedLabelstab0 should be EMPTY the first time that MainWindow::configFunction() is called
     //should only contain values after MainWindow::configApply is called. 
        for(int i = 0; i < varNameQ.size(); i++)
        {
     //            qDebug() << "labeling " << varNameQ.at(i);
            QHBoxLayout *hboxtest = new QHBoxLayout;
            QCheckBox *checkBox = new QCheckBox;
            QLabel *label = new QLabel();
    
            hboxtest->addWidget(checkBox);
            hboxtest->addWidget(label);
    
            label->setText(varNameQ.at(i));
    
            qDebug() << "before isEmpty check";
            if(!checkedLabelstab0.isEmpty()) 
            {
                qDebug() << "before for loop";
                for(int i = 0; i < checkedLabelstab0.count(); i++)
                {
                    qDebug() << "iteration " << i;
                    QLabel *testLabel = new QLabel();
                    testLabel = checkedLabelstab0.at(i);
     //                    testLabel->setText("Label ["+QString::number(i)+"]");
                    qDebug() << "This is testLabel " << testLabel->text();
                    testLabel = NULL;
                    delete testLabel;
                }
            }
    
    
            vbox0->addLayout(hboxtest);
        }
        in_0.seek(0);
    }
    file1.close();
     //*************This is done 3 more times for each of the remaining files.
    
     vbox0->setSizeConstraint(QLayout::SetFixedSize); //important to keep scrolling active
    vbox1->setSizeConstraint(QLayout::SetFixedSize);
    vbox2->setSizeConstraint(QLayout::SetFixedSize);
    vbox3->setSizeConstraint(QLayout::SetFixedSize);
    
    tab0->setObjectName("tab0");
    tab0->setLayout(vbox0);
    sa0->setWidget(tab0);
    
    tab1->setObjectName("tab1");
    tab1->setLayout(vbox1);
    sa1->setWidget(tab1);
    
    tab2->setObjectName("tab2");
    tab2->setLayout(vbox2);
    sa2->setWidget(tab2);
    
    tab3->setObjectName("tab3");
    tab3->setLayout(vbox3);
    sa3->setWidget(tab3);
    
    QPushButton *configApplyButton = new QPushButton("Apply");
    QPushButton *configCancelButton = new QPushButton("Cancel");
    
    myHbox->addWidget(configApplyButton);
    myHbox->addWidget(configCancelButton);
    
    configTabArea->addTab(sa0, tr("file1"));
    configTabArea->addTab(sa1, tr("file2"));
    configTabArea->addTab(sa2, tr("file3"));
    configTabArea->addTab(sa3, tr("file4"));
    
    configMainVbox->addWidget(configTabArea);
    configMainVbox->addLayout(myHbox);
    
    connect(configApplyButton, SIGNAL(clicked(bool)), this, SLOT(configApply()));
    connect(configApplyButton, SIGNAL(clicked(bool)), configScreen, SLOT(accept()));
    connect(configCancelButton, SIGNAL(clicked(bool)), configScreen, SLOT(accept()));
    
    configScreen->setLayout(configMainVbox);
    configScreen->setWindowTitle("Set your file's configurations");
    
    configScreen->setAttribute(Qt::WA_DeleteOnClose);
    configScreen->exec();
     }
    

    and this is the MainWindow::configApply(); slot that is called in the previous function

    void MainWindow::configApply()
    {
    QList<QTabWidget*> AllTabWidgetList = configScreen->findChildren<QTabWidget*>();

    QScrollArea *sa_0 = new QScrollArea;
    QScrollArea *sa_1 = new QScrollArea;
    QScrollArea *sa_2 = new QScrollArea;
    QScrollArea *sa_3 = new QScrollArea;
    
    QWidget *file1Tab = new QWidget;
    QWidget * file2Tab = new QWidget;
    QWidget * file3Tab = new QWidget;
    QWidget * file4Tab = new QWidget;
    
    sa_0 = qobject_cast<QScrollArea*>(AllTabWidgetList.at(0)->widget(0));
    sa_1 = qobject_cast<QScrollArea*>(AllTabWidgetList.at(0)->widget(1));
    sa_2 = qobject_cast<QScrollArea*>(AllTabWidgetList.at(0)->widget(2));
    sa_3 = qobject_cast<QScrollArea*>(AllTabWidgetList.at(0)->widget(3));
    
    file1Tab = sa_0->widget();
    file2Tab = sa_1->widget();
    file3Tab = sa_2->widget();
    file4Tab = sa_3->widget();
    
    layoutsFromtab0 = sa_0->findChildren<QHBoxLayout*>();
    layoutsFromtab1 = sa_1->findChildren<QHBoxLayout*>();
    layoutsFromtab2 = sa_2->findChildren<QHBoxLayout*>();
    layoutsFromtab3 = sa_3->findChildren<QHBoxLayout*>();
    
    qDebug() <<"count of hboxlayouts in tab0 is " << layoutsFromtab0.count();
    qDebug() <<"count of hboxlayouts in tab1 is " << layoutsFromtab1.count();
    qDebug() <<"count of hboxlayouts in tab2 is " << layoutsFromtab2.count();
    qDebug() <<"count of hboxlayouts in tab3 is " << layoutsFromtab3.count();
    
        int size = layoutsFromtab0.size();
    
        labelsFromtab0.clear();
        checkedLabelstab0.clear(); // makes sure that checked labels are checked for checking each run through.
    
        for(int i = 0; i < size; i ++)
        {
            for(int j = 0; j < layoutsFromtab0.at(i)->count(); ++j)
            {
                if(!layoutsFromtab0.at(i)->itemAt(j)->isEmpty())
                {
                    if(std::strncmp(layoutsFromtab0.at(i)->itemAt(j)->widget()->metaObject()->className(), "QCheckBox", 9) == 0)
                    {
                        QWidget *w = new QWidget();
                        w = layoutsFromtab0.at(i)->itemAt(j)->widget();
    
                        if(qobject_cast<QCheckBox*>(w)->isChecked())
                        {
                            checkedLabelstab0.append(qobject_cast<QLabel*>(layoutsFromtab0.at(i)->itemAt(j+1)->widget()));
                            
                        }
                    }
                    else if (std::strncmp(layoutsFromtab0.at(i)->itemAt(j)->widget()->metaObject()->className(), "QLabel", 6) == 0)
                    {
                        labelsFromtab0.append(qobject_cast<QLabel*>(layoutsFromtab0.at(i)->itemAt(j)->widget()));
                    }
                }
            }
        }
      }
    

    and just for clarification's sake, here is a photo of the configScreen dialog that I'm dealing with.


  • Qt Champions 2016

    hi
    Ok.
    It does seem fine.
    im confused why you do
    if(std::strncmp(layoutsFromtab0.at(i)->itemAt(j)->widget()->metaObject()->className(), "QCheckBox", 9) == 0)
    and not
    tab0->findChildren<QCheckBox*>(); U can ask to find only direct children.

    But we need to have small talk about qobject_cast
    think of it as asking "is this Object of this type." ?
    If yes, it returns NOT NULL; else NULL;

    so when you do
    if(qobject_cast<QCheckBox*>(w)->isChecked()) {
    checkedLabelstab0.append(qobject_cast<QLabel*>(layoutsFromtab0.at(i)->itemAt(j + 1)->widget()));

    it really makes no sense. as if its Not a QCheckBox*, then you will
    get NULL and say NULL->isChecked()) and crash.

    To make sense it should be
    QCheckBox* cb=qobject_cast<QCheckBox*>(w);
    if( cb) { if (cb->isChecked()) ...

    is it in configApply, that list goes empty ?



  • @mrjj

    Thank you for telling me about qobject_cast. I thought I was casting some object to another type of object.

    and oh my goodness you've done it again...
    You've led me in the right direction and I can now see the text of the labels. instead of passing the entire list of labels around, i just created a QStringList and put the label->text() in there.

    THANK YOU


  • Qt Champions 2016

    @mar0029
    :)

    • . I thought I was casting some object to another type of object.
      You are. That is correct. But if you cast something that not possible
      you get NULL.
      So using it directly is slightly risky :)
      In case it fails.

    Well if u only need the Text from the checked, then a QStringList seems fine :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.