How to initialize over a 100 QLabel in an efficient way - c++

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.

Related

Putting multiple calculations into a for-loop that uses variables based on iteration number

What is the best way to organize the following into a for loop that iterates X times, but requires updating the variables (velocity, currentPose, targetPoint) depending on the iteration number?
velocity1 = computeVelocity(currentPose1, targetPoint1);
velocity2 = computeVelocity(currentPose2, targetPoint2);
...
velocityX = computeVelocity(currentPoseX, targetPointX);
The for loop would ideally look something like this:
for (int i=0; i<X; i++)
{
velocity_i = computeVelocity(currentPose_i, targetPoint_i);
}
Since for each velocity, there will be an associated (and possibly distinct) currentPose and targetPoint, one way to do it it to have all these variables as std::vectors, or std::array if you know at compile time how many items you will have to store. Then your loop could look like this:
for (int i=0; i<X; i++)
{
velocity[i] = computeVelocity(currentPose[i], targetPoint[i]);
}
I don't think that wanting the i to be a part of the variables' name is doable (although there might be some way to do it using preprocessor macros and the # concatenation operator, I have not thought about it), nor would it be usual C++ code.
For a C++ programmer the vector/array approach is the more natural one.

Qt GUI how can I put these labels into an array

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;
}

Efficient way to make an array of labels

I'm making a board game and I need to display a 15 x 15 array in my gui. I decided to go with individual labels which contains one element of the array. This means I do have quite a lot of labels. I gave each label the name "tile_0_0" with the first 0 being the row and the second 0 being the column. This was quite easy to do in qt.
The problem however is that I ofcourse can't simply use 2 forloops to access each tile since you can't use variables in names. ("tile_i_j" does not exist.) To solve this I decided to make an array which contains each and every label. I however cannot initialise the array efficient because of the earlier mentioned problem.
So the question is: How can I avoid having to write a giant block of code?
A small piece of the current code:
Ui::BoardView *ui = new UI::BoardView; // BoardView is my class
QLabel* m_boardLbArray[8][8];
m_boardLbArray[0][0] = ui->tile_0_0;
m_boardLbArray[0][1] = ui->tile_0_1;
m_boardLbArray[0][2] = ui->tile_0_2;
m_boardLbArray[0][3] = ui->tile_0_3;
m_boardLbArray[0][4] = ui->tile_0_4;
// ...
Note: Sorry that I didn't post a part of code you could simply copy and run, but I do not know how since it's gui related.
It sounds like you are creating your tiles(QLabels) in Qt Designer; A cleaner way to achieve this is to create them programatically. You can do something like add a Grid Layout to your form in Designer in the location you want them, and then do:
QGridLayout *layout = ui->gridlayout;
QLabel* m_boardLbArray[8][8];
for(int row=0; row<8; row++)
for(int col=0; col<8; col++)
{
m_boardLbArray[row][col] = new QLabel(this);
m_boardLbArray[row][col]->setText(tr("This is row %1, col %2")
.arg(row).arg(col));
layout->addWidget(m_boardLbArray[row][col], row, col);
}

Assign values to multiple edit boxes, given their names

i am currently doing some programming in Borland C++ Builder 6.
I have 24 edit boxes(a visual component, with a text field) and i want to insert some values in the boxes, now i do it like this:
Edit1->Text=1;
Edit2->Text=2;
Edit3->Text=3;
...
Edit24->Text=24;
but i want to have something like this:
for(int i=1; i<25;i++){
Edit"i"->Text=i;
}
i think i have to make an array of objects or something.
Can any body help me with this? I don't have a lot of experience with objects and stuff like that.
There is a FindComponent function in VCL. It is used to find a component by it's name.
In your case it will look something like:
TEdit * tmp;
for( int i = 0; i < 24; i ++ )
{
tmp = (TEdit*)MyForm->FindComponent("Edit" + IntToStr(i) );
tmp->Text = i;
}

Retrieve value of QTableWidget cells which are QLineEdit widgets

I create a QLineEdit,set a validator and put it on the table with this code:
ui->moneyTableWidget->setCellWidget(rowsNum, 1, newQLineEdit);
Then I've got another class for manipulating the table's data doing the sum of every value of a column. Here's the code:
int Calculator::calculatePricesSum(QTableWidget &moneyTableWidget){
double total = 0;
QWidget *tmpLineEdit;
QString *tmpString;
for(int row=0; row<moneyTableWidget.rowCount(); row++){
tmpLineEdit = (QLineEdit*)moneyTableWidget.cellWidget(row,1);
tmpString = tmpLineEdit.text();
total += tmpString->toDouble();
}
return total;
}
But the building fails with this error:
/home/testpec/src/nokia
QT/MoneyTracker-build-simulator/../MoneyTracker/calculator.cpp:11:
error: cannot convert ‘QLineEdit*’ to
‘QWidget*’ in assignment
Why this convertion error?
Another subquestion: passing the table as reference saves memory right? Could this be the problem? Im developing for a Nokia smartphone and I think passing the object by value is a waste of memory...(sorry if is a dumb question but I'm a little rusty with C++ and all the pointers stuff...)
When you declare your tmpLineEdit, you should be declaring it as a QLineEdit* instead of a QWidget*. Your loop grabs the widget, casts it to a QLineEdit* and then tries to put it back into a QWidget*. Also, I'd recommend using qobject_cast<QLineEdit*> (or dynamic_cast) so that you can ensure the cast succeeded.
int Calculator::calculatePricesSum(QTableWidget &moneyTableWidget){
double total = 0;
QLineEdit* tmpLineEdit;
QString tmpString;
for(int row=0; row < moneyTableWidget.rowCount(); row++)
{
tmpLineEdit = qobject_cast<QLineEdit*>(moneyTableWidget.cellWidget(row,1));
if(NULL == tmpLineEdit)
{
// Do something to indicate failure.
}
tmpString = tmpLineEdit->text();
total += tmpString.toDouble();
}
return total;
}
As for your second question, passing by reference is probably a good idea - I know some of the classes in Qt (QImage in particular) use reference counting and implicit sharing so that you can pass around by value without worrying about the implications of large copy operations, but I'm not sure if a QTableWidget is in that category as well.