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? -
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 getQObject(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 triedqDebug() << 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, withqDebug() << 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.
-
@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 callcheckBoxLabel.at(0)->text();
it returns a null value. Why wouldn't the value stay the same? -
@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. -
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. -
@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 signalvoid 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. UsingmyListOfLabels->count();
on the second time opening the dialog, provides the suspected number of items. -
@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. -
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 functionvoid 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.
-
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 ?
-
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
-
@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 :)
- . I thought I was casting some object to another type of object.