Array of QLabel
-
Hello,
I want to sort the labels alphabetically in a horizontal layout full of QLabels.
I can keep the text of the labels in a vector and sort them alphabetically with Qcollator. The problem is not here.
I am using a QList or QMap where I use these labels. I'm putting my labels in it without any problem.
However, when adding my labels to the layout from this list, the program crashes. but why ?void dragglableWidgetUstBar::sortLabels() { if(!lay->isEmpty()) { QVector<QString> veclist; for(int i = 0 ; i<lay->count();i++) { QWidget *widget = lay->itemAt(i)->widget(); if(widget) { krnLabel *label = qobject_cast<KrnLabel *>(widget); if(label) { veclist.append(label->text()); //The texts of the labels are load to the vector. labelMaps.insert(label->text(),label); // Label and text information is loadto qmap } } } QCollator collator; collator.setNumericMode(true); std::sort( veclist.begin(), veclist.end(), [&](const QString &file1, const QString &file2) { return collator.compare(file1, file2) < 0; // Sort alphabetically by string. }); if ( lay->layout() != NULL ) { QLayoutItem* item; while ( ( item = lay->layout()->takeAt( 0 ) ) != NULL ) // delete items in layout { delete item->widget(); delete item; } } for(auto &str : veclist) { lay->addWidget(labelMaps[str]); //ERROR!! / } } }
-
this window is coming.
In a little test I made, it works like this without any problems:
KrnLabel *testlabel = new KrnLabel(view,_dataList,"testlabel",id=4); labels.append(testlabel); ... qDebug()<<"label name" : <<labels.at(0)->text(); // it works...
but as in the code I shared at the top; the program crashes when using the label I added from the layout...
-
@JonB said in Array of QLabel:
What does the debugger tell you (e.g. stack trace) for a start?
You need to look at he stack trace pane. You always need to look at the stack trace pane when you get a crash. Nobody wants to look through a whole program to trace down a crash somewhere when the first vital piece of information is given by the debugger. If you learn to do this you may even be able to see the problem and the fix yourself!
As a separate point: the choice to implement "sorting of some existing labels" via: copy their text, delete each
QLabel
and create newQLabel
s from their text seems "not good" to me for a number of reasons. It would be preferable to write code which removes (but not deletes) the existingQLabel
s from their layout and re-uses them. -
@JonB said in Array of QLabel:
You need to look at he stack trace pane
Are you talking about this area?
@JonB said in Array of QLabel:
It would be preferable to write code which removes (but not deletes) the existing QLabels from their layout and re-uses them.
yes, I'm currently researching how to change item's location in layout, but I haven't found anything yet.
-
@Nevez
So you can now see where it is crashing. What do you think you should do about it? What is the first thing you should print out or examine in that line? And why is your source code now different from what you posted?When you have answered, I will tell you what I presume is causing crash in your code :)
-
@Nevez said in Array of QLabel:
I am using a QList or QMap
...so which of the two is used?
labelMaps.insert(label->text(),label);
look s like it isQMap<QString, QLabel *> labelMaps
lay->addWidget(labelMaps[str]);
looks like you should examine the documentation of QMap and QList.
You call will castQString str
to aqsizetype
and very likely overshoot the range oflabelMaps
. Then it crashes.Assuming that
labelMaps
is aQMap
, this is your friend.
The call in that case islay->addWidget(labelMaps.value(str));
-
@Nevez
My understanding of your code:labelMaps.insert(label->text(),label); // Label and text information is loadto qmap }
This inserts
label
, which is the (pointer to) the actualQLabel
, into your map. Note that it does not copy it (nor can you copy aQWidget
).delete item->widget();
This actually deletes the widget on the layout. This is the
QLabel
still pointed to in your saved map.lay->addWidget(labelMaps[str]); //ERROR!! /
The widget has now been deleted, so you cannot re-add or do anything to it.
You cannot afford to delete the labels if you wish to re-add them. I think you want to delete the current layout items but not their widget? Does
delete item
withoutdelete item->widget()
solve your problem? Your earlier copy-to-map code checks if item widget is aKrnLabel *
, to be robust you ought check that in your later removal from layout/re-add of widget.UPDATE
I see @Axel-Spoerl has posted while I was typing this in. My analysis of your problem is quite different from his (I didn't look at yourQMap
access code, took it you have that right).... -
@JonB said in Array of QLabel:
My analysis of your problem is quite different from his
Well, I stumbled over that one and didn't look any further. But @JonB is also right (nothing else expected).
-
@Axel-Spoerl
Just so @Nevez knows, his map access code is actually OK. He will be using aQMap
not aQList
. OnlyQList
has theqsizetype
, and I should be horrified if the compiler converted aQString
to aqsizetype
even if wereQList
:) So no "overshooting" here.lay->addWidget(labelMaps.value(str))
would be safer here, because (although it does work here):labelMaps[str]
returns a reference to the value but would silently create a default value at[str]
if not found. OP's should be found OK, so it will work in this case, but.value(str)
which would not do that would be nicer. Code ought also check value found and returned non-nullptr
, asaddWidget()
would not like that and could have been cause of crash. -
@JonB and @Axel-Spoerl
Firstly , thank you so much for your amazing support and comments.@Axel-Spoerl said in Array of QLabel:
Assuming that labelMapsis a QMap, this is your friend.
The call in that case is lay->addWidget(labelMaps.value(str));Yes, I tried this method too. But the crash continued. What @JonB said in his comment caught my attention.
@JonB said in Array of QLabel:
This actually deletes the widget on the layout. This is the QLabel still pointed to in your saved map.
I can't believe how I missed this point.
This was the main point in my solving the problem.so I wrote a new code that will remove the items from the layout without completely deleting them.
And I used the qmap method as @Axel-Spoerl said. no problem now
it's working.QLayoutItem* item; while ( !lay->isEmpty() && ( (item = lay->layout()->takeAt( 0 ) ) != NULL ) ){ layout()->removeItem(item); } delete item; for(auto &str : veclist) { lay->addWidget(labelsMap.value(str)); }
As you can see in the picture, the labels are sorted without any problems, and the models in them are currently working without any problems.