Refer to an interface object name with a variable (string)
Hello,
I'm developing an app that has 100 line edits.
I named them t001, t002, t003, ..., t100
I want to convert the value of each text in the line edits to double (no problem there) and save it in a vector, called t[].
I don't want to repeat the following code a hundred times over:
Code:
double t[100];
int count1 = 0;
if(ui->t001->text() != "")
{
t[count1] = ui->t001->text().toDouble();
count1++;
}
So, is there anyway I can use the name of the object as a string variable, so I can use a loop? Like:
Code:
double t[100];
int count1 = 0;
for(count1 = 0; count1 < 100; count1++)
{
current_element = "t" + count1+1;
if(ui->current_element->text() != "")
t[count1] = ui->current_element->text().toDouble();
}
edited: I know this code wouldn't work and needs adapting in at least 2 parts, but still, what I need answered is the main question in the thread.
Thanks in advance.
Re: Refer to an interface object name with a variable (string)
Why not simply put the line edits in a list as well?
Or even create them programatically in the first place into a list.
Cheers,
_
Re: Refer to an interface object name with a variable (string)
I don't understand how putting the objects in a list would help me, I'm a newbie, that's why I posted it in this board.
I tried googling it, the key words are too common.
Anyway, this should make my problem very clear for those who did not understand:
Code:
double t[100];
int count1 = 0;
for(count1 = 0; count1 < 100; count1++)
{
if(count1 < 9)
objectname = "t0";
else
objectname = "t";
objectname
+= QString::number(count1
+1);
t[count1] = ui->objectname->text().toDouble();
}
And, when I try to build this, I get:
'objectname': is not a member of 'Ui::MainWindow'
since I'm trying to use ui->objectname instead of ui->t01 or ui->t02 or ui->t03, and all the way to t100, one by one.
Re: Refer to an interface object name with a variable (string)
Quote:
Originally Posted by
guiismiti
I don't understand how putting the objects in a list would help me,
You would iterate over the list the same way you are iterating over 't' in your code snippet.
Re: Refer to an interface object name with a variable (string)
Re: Refer to an interface object name with a variable (string)
thank you all, i'll look it up and test.
Re: Refer to an interface object name with a variable (string)
Quote:
I don't understand how putting the objects in a list would help me
Instead of creating your QLineEdit objects in Qt Designer, create them in code and insert them into a vector:
Code:
// in the constructor for your widget
// assumption is that there is a layout to handle the 100 line edits
// also assume there is a QVector< QLineEdit * > * pEdits member variable
pEdits
= new QVector<
QLineEdit * >
( 100,
0 );
for ( int i = 0; i < 100; i++ )
{
pLayout->addWidget( pEdit );
pEdits[ i ] = pEdit;
}
Now if you want to retrieve the text from the "nth" line edit, you simply do this:
Code:
t[ n ] = pEdits[n]->text().toDouble();
Re: Refer to an interface object name with a variable (string)
Creating the line edits by code would get too complicated for me, I'm using a few stacked widgets.
Re: Refer to an interface object name with a variable (string)
Quote:
Originally Posted by
guiismiti
Creating the line edits by code would get too complicated for me, I'm using a few stacked widgets.
That's really not a problem at all. Even if you were to copy and paste the same code 100 times, it would still be beneficial. And you don't have to do that, you can create your widgets based on some array or whatever can hold the ui definition and is iterable.
Re: Refer to an interface object name with a variable (string)
Quote:
Originally Posted by
guiismiti
I don't understand how putting the objects in a list would help me
A list is a sequential container, its element can be accessed by numerical index, like the array.
If you have the elements in a list, you can access the result value array index and the source element with the same integer value.
You can even use an array of pointers instead of the list, or a vector.
If you can't create the elements in code, you still need to initialize this container once, while every other access can then be based on numerical index.
Cheers,
_
Re: Refer to an interface object name with a variable (string)
Quote:
Originally Posted by
anda_skoa
A list is a sequential container
Thank you once again.
Is there anything about lists in the Qt docs? I would like to explore syntax and read about it.
Re: Refer to an interface object name with a variable (string)
See documentation for QList and QVector.
Cheers,
_
Re: Refer to an interface object name with a variable (string)
Quote:
Creating the line edits by code would get too complicated for me, I'm using a few stacked widgets.
As wysota and others have said, if you don't want to create the widgets in code, you can still retrieve their pointers and store them in a list or vector:
Code:
// In the constructor for each widget in the stack:
ui->setupUi( this );
pVector[ 0 ] = ui->t000;
pVector[ 1 ] = ui->t001;
// etc. for the next 98 line edits
// Then, you still retrieve the text for each widget using the vector
t[n] = pVector[n]->text().toDouble();
Edit: You could avoid the cut-and-paste if you are consistent in your names for the line edits. You can then use findChild, as Lesiok suggests:
Code:
for ( int i = 0; i < 100; i++ )
{
pVector
[ i
] = findChild<
QLineEdit * >
( name
);
}
This assumes the line edits are named "t000", "t001", ... "t099".
Re: Refer to an interface object name with a variable (string)
Just remember, despite having to write less lines of code to use findChild this is actually slower to execute than 100 copy&paste of the manual code that retrieves a single pointer. So all in all it is a matter of balance between the number of lines of code you have to write (once) and the amount of code that needs to be executed (every time you run your app).
1 Attachment(s)
Re: Refer to an interface object name with a variable (string)
Quote:
Originally Posted by
wysota
Just remember, despite having to write less lines of code to use findChild this is actually slower to execute than 100 copy&paste of the manual code that retrieves a single pointer. So all in all it is a matter of balance between the number of lines of code you have to write (once) and the amount of code that needs to be executed (every time you run your app).
Yea, I thought about that.
I had the code written and ready just before I started the thread, but in my honest opinion I don't really like the idea of doing this kind of manual job when it can be avoided.
I said I have 100 elements but I actually have 3 stacked widgets with 100 each - but that doesn't affect anything, so I decided to make it simple to present the problem. All elements are essential to the app - they are results of a laboratory experiment that must be informed as float (or double, I don't really know the difference).
I haven't got much time right now (couldn't even open Qt today :( ), but I think that the list is the best option for me.
But still, does anybody know what's wrong here? I'm trying to use findChild. I have tried to use parentWidget instead of centralWidget, but no difference.
Code:
QLineEdit *lineedit
= centralWidget
->findChild<QLineEdit
*>
("t01");
The error message I get is this
'->QObject::findChild' : left operand has " type, use '.'
Edited: This may be helpful
Attachment 10913
Re: Refer to an interface object name with a variable (string)
Perhaps you need ui->centralWidget->findChild< QLineEdit * >( "t01" ) ? The compiler is probably complaining about the dereferencing because it can't find a variable named "centralWidget" in the current scope.
And you probably don't want to use centralWidget in any case - findChild will get only the first of the QLineEdit widgets it finds with a matching name in one of the stacked widgets, probably the first one in the stack. (Assuming that the line edits on each page have the same names - eg. "t01" is the first line edit on each page). You will want to retrieve each set of 100 from each stacked widget separately and store them in three separate vectors / lists.
Re: Refer to an interface object name with a variable (string)
Quote:
Originally Posted by
d_stranz
Assuming that the line edits on each page have the same names - eg. "t01" is the first line edit on each page
Not the case - it's tn for time, vn for volume and cn for concentration.
Re: Refer to an interface object name with a variable (string)
Quote:
Not the case - it's tn for time, vn for volume and cn for concentration.
Then you're lucky :) Even so, I would still retrieve the line edit pointers from their most immediate parent (eg. the individual page widgets inside the stack widget).
It's an encapsulation thing. The main window (and indeed, the rest of your app) doesn't need to know that there are 100 line edits buried down on a page somewhere in a stack widget. What it needs to know is when the array of time values has been updated. What I would do in that case is to keep all the code that retrieves the line edit pointers and keeps track of when the user changes things encapsulated within the parent widget that contains the line edits. When the user changes a value, you update it in the vector or list (which is held by the parent widget containing the line edits), and then emit a custom signal ("timeValuesChanged( const QVector< double > & )" ) with the new array of time values. Likewise volume and concentration.
This way, you can do whatever you want to change the widgets inside the stack, the only thing the main window will know is that it should expect a signal like that when the values change. You could even substitute an object that reads time, volume, and concentration values from a file (or sensor array), and as long as it emits the same signal, the app won't know the difference.
Re: Refer to an interface object name with a variable (string)
Quote:
Originally Posted by
guiismiti
I said I have 100 elements but I actually have 3 stacked widgets with 100 each - but that doesn't affect anything, so I decided to make it simple to present the problem. All elements are essential to the app - they are results of a laboratory experiment that must be informed as float (or double, I don't really know the difference).
I would have a configuration file (e.g. xml) that would list all the parameters and at runtime I would read the file, create the widgets based on it and so on. Should be really easy. If at any time you decide to modify the widgets, it is enough to modify the configuration file and the program will follow.
2 Attachment(s)
Re: Refer to an interface object name with a variable (string)
Things seem to be working fine right now.
Although, I've got this little problem going on with the interface - the first page of the stacked widget is always fully displayed, but all the others are not (like in the images). It doesn't matter which is the first page, all the other ones will be like in the second image, with a huge gray square on the right side.
Here is the first page:
Attachment 10925
Here is the second page:
Attachment 10926
Please let me know if you need any more info.
Again, thank you very much, I really appreciate it.