Qt GUI how can I put these labels into an array - c++

How can I set up my labels to be in an array to be called on later? I can't seem to get a hand on what type labels is in order to pull this off.
What I have is this, however this would be rather ugly to maintain.
If I could change this
ui->label_11->setVisible(false);
ui->label_5->setVisible(false);
ui->label_12->setVisible(false);
ui->label_44->setVisible(false);
ui->label_43->setVisible(false);
ui->label_9->setVisible(false);
ui->label_10->setVisible(false);
ui->label_42->setVisible(false);
to this, it would be most preferable. But, perhaps I'm thinking about this in the wrong way.
SometypeIdoNotKnow values[7] = {ui->label_11,
ui->label_5,
ui->label_12,
ui->label_44,
ui->label_43,
ui->label_9,
ui->label_10,
ui->label_42};
for (int i=0; i <= 7; i++){
values[i]->setVisible(false);
}

If your compiler is not ancient, use C++11:
// If you only want to iterate some labels
auto const labels = {ui->label_11, ui->label_12, ui->label_44,
ui->label_43, ui->label_9, ui->label_10,
ui->label_42};
// If you want to iterate all labels
auto labels = findChildren<QLabel*>();
for (auto label : labels) label->hide();

Thank you #drescherjm for the answer.
this seems to have worked.
QLabel* values[7] = {ui->label_11,
ui->label_12,
ui->label_44,
ui->label_43,
ui->label_9,
ui->label_10,
ui->label_42};
for (int i = 0; i < 7; i++){
values[i]->setVisible(false);
qDebug() << i;
}

Related

Multiple statements in a ranged for loop

I'd like to know if it's possible to convert this expression
vector<Mesh>::iterator vIter;
for(int count = 0, vIter = meshList.begin(); vIter < meshList.end(); vIter++, count++)
{
...
}
into something along the lines of C++ 11
I'd like to get something like this:
for(auto count = 0, auto mesh : meshList; ; count++)
{
...
}
Is there a way to do this?
No, it is not possible. The best you can do is the following:
int count = 0;
for(auto &mesh : meshList)
{
...
++count;
}
For completeness's sake alone, I just want to point out that you can define those two in the for loop's init-list (if your really want to) by (cheating and) aggregating them:
for(struct { int count; decltype(meshList)::iterator vIter; } _{0, meshList.begin()} ;
_.vIter < meshList.end(); _.vIter++, _.count++)
{
// ...
}
See it live
But as you may have noticed it's verbose, ugly, and totally not worth it. The solution in Remy's answer is better by a factor of 100 at least.

How to initialize over a 100 QLabel in an efficient way

I want to have the ability to update over 100 labels, so I was going to put them in an array like this:
voltage_label_array[0] = this->ui->Voltage_0;
voltage_label_array[1] = this->ui->Voltage_1;
voltage_label_array[...] = this->ui->Voltage_2;
voltage_label_array[...n] = this->ui->Voltage_n;
and then have this method
void MainWindow::updateValue(int i, int voltage){
voltage_label_array[i]->setText(QString::number(voltage));
}
but having 100 lines to set this up seems like a bad idea. Is there a way I can initialize a QLabel array inside a for loop or something?
If you need to do this, something is horribly wrong with your design. But it is possible.
Assuming your labels are named Voltage_0 to Voltage_99:
for(int i = 0; i < 100; ++i) {
auto ptr = this->findChild<QLabel*>(QString("Voltage_%1").arg(i));
voltage_label_array[i] = ptr;
}
This "solution" uses Qt's runtime reflection and carries the expected performance penalties.
But if you need to display several similar values, look up QListWidget and similar classes.

Showing different windows 1 by 1

I have a problem with my code. I want to show different windows one by one by clicking the "Next" button to show the next one like this:
int i = 0;
do {
auto polyLines = new ExportPolyLines(nodeNames);
polyLines->show();
if (!polyLines->isVisible()) {
i++;
}
} while (i < 3);
The code compiled but did not work!
Can anyone help me about this?
As an improvement to your comment I would suggest that you fix the memory leak.
if (_logIsSelected)
{
for (int i = 0; i < _selectedWellLogs.size(); i++)
{
auto exportLogsData = new ExportsLogs(_selectedWellLogs[i], _wellLogsName[i], _folder);
exportLogsData->exec();
delete exportLogsData; // Free the memory that has been used for ExportLogs
exportLogsData = nullptr; // Not really necessary here, but good practice
}
}

C++ resize array to smaller size keep same name delete old place in array

I have an array of space object (my thing) that I need to reduce but keep the same name in order to handle some collisions. I set my array up like:
ufo** ufoAr = new ufo*[numberOfUfos];
for (int i=0; i<numberOfUfos; i++) {
ufoAr[i] = new ufo(randomIntBetween(1630, 70), randomIntBetween(860, 45));
}
and when i detect a collision I want to resize my array with two less and delete the two specific elems of array. like here:
//look through all the ufoAr[]
for (int i=0; i<numberOfUfos; i++) {
//look through ufoAr[] again to see other objects
for(int j=0; j<10; j++) {
//if the same
if (i==j){ continue; }
else {
//find a collision
if(ufoAr[i]->collision(ufoAr[j]->sp)) {
//Array::Resize(ufoAr, numberOfUfos-2);
//numberOfUfos = numberOfUfos - 2;
// ------ TRY TO RESIZE ARRAY TO -2 BUT SAME NAME WITHOUT iTH AND jTH ELEM
ufoAlive[i] = false;
ufoAlive[j] = false;
}
}
}
}
I would greatly appreciate any help on resizing the array, thanks in advanced. I am really struggling and need another opinion. thanks
Jack
To do this, you will need to FIRST create a new array, e.g.
ufo** ufoArTmp = new ufo*[numberOfUfos-2];
then copy the contents [you want to keep] of ufoAr into ufoArTmp. Once that is done, you do delete [] ufoAr, and finally ufoAr = ufoArTmp; to update the original pointer. do NOT delete ufoArTmp at this point, as it's the same value as is now in ufoAr, and you want to keep that, right.
Obviously pay special attention to numberOfUfos being less than 2 when you start... ;)
Edit, in reading through the other code:
Don't do this:
if (i==j){ continue; }
else {
much better:
if (i!=j) {
The simplest way to do this is to use std::vector and let that handle the resizing for you.
cplusplus.com reference
cppreference page

Remove specific items from a listbox in MFC

CString dance[] = {L"Atb", L"Tiesto", L"Madonna", L"Paul van Dyk", L"Armin van Burren", L"Jennifer Lopez"};
for(int i = 0; i < m_ItemsListBox.GetCount(); ++i)
{
CString item;
int length = m_ItemsListBox.GetTextLen(i);
m_ItemsListBox.GetText(i, item.GetBuffer(length));
for(int j = 0; j < sizeof(dance)/sizeof(*dance); ++j)
{
if(item != dance[j])
{
m_ItemsListBox.DeleteString(i);
}
}
}
I'm trying to remove from a listbox(m_ItemsListbox) all elements that are not part from the CString array. But how I coded it doesnt work, because if the first element its different it will delete it without searching the entire array.
Doesn't seemed like a hard task but I really have no idee how to do it. I think one way should be to use a CList instead of the array because it has a find() method, but I don't like it because I have to manually add all the elements, do you guys have another idee? Or the CList solution is the only one ?
Sorry, I'm a MFC begginer. Thanks for your time.
Hmmm I wouldn't be comfortable deleting things from the list box while iterating through the items in the listbox seems to be asking for problems down the line.
Honestly you could do something like this, I've just whipped together - construct a list of all the item indexes you want to remove and remove them at the end.
CList<int, int> ListIndexItemsToRemove;
for(int i = 0; i < m_ItemsListBox.GetCount(); ++i)
{
CString item;
int length = m_ItemsListBox.GetTextLen(i);
m_ItemsListBox.GetText(i, item.GetBuffer(length));
bool isMatchFound = false;
for(int j = 0; j < sizeof(dance)/sizeof(*dance); ++j)
{
if(item == dance[j])
{
isMatchFound = true;
}
}
if (!isMatchFound)
ListIndexItemsToRemove.AddHead(i);
}
for(int i = 0; i < ListIndexItemsToRemove.GetCount(); ++i)
m_ItemsListBox.DeleteString(ListIndexItemsToRemove.GetAt(ListIndexItemsToRemove.FindIndex(i));
but - it may be better to clear the whole list and refill it everytime something changes, as Martin says (if it doesn't affect anything.
For dynamic lists I tend to store data in its own variable and clear/re-populate the list when that data changes. Especially as the list gets bigger re-adding the strings tends to be much faster than doing searches through the list and/or original source.