Re: subclass QLineEdit to have an index
The OPs question makes more sense if you understand how Visual Basic 6 handled controls on a form. A form could have a number fully independent text boxes (equivalent of QLineEdit) each with an individual name as you would see in a Qt form. However, VB6 also had an upper limit on the number of controls on a form (256 IIRC). If you needed to exceed that then VB6 provided a method that could be used to provide a flyweight version of a control with single name and index to access many instances of that control type: a control array. That is, edit(1) referred to the first editor, edit(2) to the second, etc. but there was only one actual control object. Once the control gained an index its event handlers (like slots) were automagically passed an integer index number as their first argument.
The most direct translation of that is to a list of QLineEdits and a QSignalMapper (but the behaviours also bear striking resemblance to the transient editor in item views). I guess that in Python th "control array" might look some like this (only passing knowledge of Python):
Code:
self.TextBox = []
for i in range(0, 1500):
layout.addWidget(self.TextBox[i])
# and later
Str = TextBox[123].text()
Actually, the QSignalMapper docs have an almost complete example of the entire process including channelling signals from 1500 widgets through a single set of slots with an integer index.
Re: subclass QLineEdit to have an index
Quote:
The OPs question makes more sense if you understand how Visual Basic 6 handled controls on a form.
And the OP seems to want to force Qt and Python to use the same semantics, even though it isn't possible using the syntax he is proposing. As we have already suggested, the closest thing to that is to use QSignalMapper, but that doesn't appear to satisfy the need to adhere to VB syntax. My head hurts from pounding it against the wall, so I'll leave it to the rest of you to carry on.
Re: subclass QLineEdit to have an index
I am quite familiar with tableViews and that is not an acceptable solution. My earlier description was considerably shortened and was meant only to demonstrate why I want to subclass a LineEdit(). As I have mentioned before, I don't really need a different way to do what I want, I need help doing what I do want to do, which is to subclass a LineEdit so that I can access it with LineEdit(item#).setText()
Re: subclass QLineEdit to have an index
For the nth (and last for me) time, you cannot access an existing LineEdit, subclassed or not, using the syntax LineEdit( item#). The syntax you seem bent on using will create a new LineEdit instance (as I explained several posts ago). It will not give you a pointer to a LineEdit instance that you create using the same syntax and place on a form. If you think you can access a previously-created LineEdit this way, you are wrong. Python and C++ do not work the same way as VB and Excel (as ChrisW also explained). You may be able to use your syntax in a VB macro, but you cannot use the same syntax in a Python script.
The languages are different. They don't work the same way. What you can do in VB you can't do in Python or C++. And behind the scenes, VB is likely doing exactly the same thing as we have told you that you must do - it has created some type of lookup mechanism that stores these instances and allows the type of syntax you want to use. To do the same thing in Python, you must write your own lookup mechanism, and you cannot use VB syntax as part of that.
Sorry if this sounds rude, but your stubbornness in refusing to accept that you cannot do in Python what you might be able to do in VB is pretty frustrating. You have received advice from several people who regularly give their free time to try to help others who ask questions here, and we have tried to be patient in explaining why the syntax you want to use won't work and in offering you solutions which will work in Python and C++. You keep insisting that your way is the only way. Good luck with it.
Re: subclass QLineEdit to have an index
@nlgootee
You realize that, to the rest of the world, porting an algorithm from a language to another generally means preserving the semantics while adopting the syntax and best practices of the target language?
But hey, good news, C++ lets you define your own operators. So, technically, nothing stops you from writing your own insane vector class and get exactly the syntax you want. Behold the majesty of C++ which lets you have your way without listening to reason; I get goosebumps sometimes:
Code:
#include <cstddef>
#include <vector>
class MyStrangeVector {
public:
m_vec.push_back(le);
}
// Index using () and dereference, just because we can
return *m_vec[index];
}
private:
std::vector<QLineEdit *> m_vec;
};
void f() {
MyStrangeVector LineEdit;
// Populate the vector
for (size_t i = 0; i < 1650; ++i) {
// ...
LineEdit.add(le);
}
// All this nonsense so that we can finally write:
LineEdit(42).setText("meh");
}
Thanks. You've made my day.
Re: subclass QLineEdit to have an index
Quote:
Originally Posted by
ChrisW67
The OPs question makes more sense if you understand how Visual Basic 6 handled controls on a form. A form could have a number fully independent text boxes (equivalent of QLineEdit) each with an individual name as you would see in a Qt form. However, VB6 also had an upper limit on the number of controls on a form (256 IIRC). If you needed to exceed that then VB6 provided a method that could be used to provide a flyweight version of a control with single name and index to access many instances of that control type: a control array. That is, edit(1) referred to the first editor, edit(2) to the second, etc. but there was only one actual control object. Once the control gained an index its event handlers (like slots) were automagically passed an integer index number as their first argument.
The most direct translation of that is to a list of QLineEdits and a
QSignalMapper (but the behaviours also bear striking resemblance to the transient editor in item views). I guess that in Python th "control array" might look some like this (only passing knowledge of Python):
Code:
self.TextBox = []
for i in range(0, 1500):
layout.addWidget(self.TextBox[i])
# and later
Str = TextBox[123].text()
Actually, the QSignalMapper docs have an almost complete example of the entire process including channelling signals from 1500 widgets through a single set of slots with an integer index.
What does OP stand for? I got a very similar reply on a different list, using a dictionary. I will probably end up doing something like it but it seems like overkill for what I am trying to do.
Quote:
Originally Posted by
yeye_olive
@nlgootee
You realize that, to the rest of the world, porting an algorithm from a language to another generally means preserving the semantics while adopting the syntax and best practices of the target language?
But hey, good news, C++ lets you define your own operators. So, technically, nothing stops you from writing your own insane vector class and get exactly the syntax you want. Behold the majesty of C++ which lets you have your way without listening to reason; I get goosebumps sometimes:
Code:
#include <cstddef>
#include <vector>
class MyStrangeVector {
public:
m_vec.push_back(le);
}
// Index using () and dereference, just because we can
return *m_vec[index];
}
private:
std::vector<QLineEdit *> m_vec;
};
void f() {
MyStrangeVector LineEdit;
// Populate the vector
for (size_t i = 0; i < 1650; ++i) {
// ...
LineEdit.add(le);
}
// All this nonsense so that we can finally write:
LineEdit(42).setText("meh");
}
Thanks. You've made my day.
Cool! Can you do it in python?
Added after 22 minutes:
Quote:
Originally Posted by
d_stranz
For the nth (and last for me) time, you cannot access an existing LineEdit, subclassed or not, using the syntax LineEdit( item#).
You keep insisting that your way is the only way. Good luck with it.
Actually I never insisted that my way is the only way. I merely asked if it was possible to do it the way I wanted to and rather than the simple yes or no that I asked for, I got a whole bunch of suggestions to do something that would not accomplish what I need. Don't get me wrong, the discussion has been interesting and I may be able to use some of the answers I got, but I don't think that anyone has actually understood what I am trying to accomplish and that has been frustrating for me because I have looked back over my prior posts and it seems very clear to me. :)
Added after 28 minutes:
Ok! So I can't use the syntax that I want to use. How about this?
Code:
itemNo = 12345
name = "MyLineEdit" + itemNo
MyLineEdit.setObjectName(name)
This would give me a LineEdit named MyLineEdit12345 and I could set the text with MyLineEdit12345.setText(1) and I could access the text with string = MyLineEdit12345.text()
Re: subclass QLineEdit to have an index
Quote:
Originally Posted by
nlgootee
What does OP stand for?
Original Poster, i.e. you.
Quote:
Originally Posted by
nlgootee
I got a very similar reply on a different list, using a dictionary. I will probably end up doing something like it but it seems like overkill for what I am trying to do.
Yes, a vector or list would be better.
Quote:
Originally Posted by
nlgootee
Actually I never insisted that my way is the only way.
You insisted on a particular syntax that is not part of the language you've chosen.
Quote:
Originally Posted by
nlgootee
I merely asked if it was possible to do it the way I wanted to and rather than the simple yes or no that I asked for, I got a whole bunch of suggestions to do something that would not accomplish what I need.
You've got suggestions to do exactly what you need.
The only difference between the suggested solution of using a linear container and your insisted syntax is the use of [] instead of () for the index access.
Quote:
Originally Posted by
nlgootee
Don't get me wrong, the discussion has been interesting and I may be able to use some of the answers I got, but I don't think that anyone has actually understood what I am trying to accomplish and that has been frustrating for me because I have looked back over my prior posts and it seems very clear to me. :)
Well, we assume that you want to access the values that the user sees.
You insist that you want to work with temporary objects that are not the ones the user interacts with.
Usually a program that presents UI to the user will want to either change the values the user sees or the the user's input or both.
Quote:
Originally Posted by
nlgootee
This would give me a LineEdit named MyLineEdit12345 and I could set the text with MyLineEdit12345.setText(1) and I could access the text with string = MyLineEdit12345.text()
No.
The object name property is a value of the object, not the name of the variable holding the object.
Seriously:
- create a list named "LineEdit"
- put your line edits into that list
- access the line edits via index using the list's [] operator
The only difference to your target syntax is usage of brackets instead of parentheses.
Cheers,
_
Re: subclass QLineEdit to have an index
Quote:
Originally Posted by
anda_skoa
Original Poster, i.e. you.
No.
The object name property is a value of the object, not the name of the variable holding the object.
Cheers,
_
What is the name of the variable holding the object? I thought that it was the objectname.
Re: subclass QLineEdit to have an index
Quote:
Originally Posted by
nlgootee
What is the name of the variable holding the object?
Hmm, I would have assumed you had had a look at some Python tutorial before starting on an actual application.
The name of the variable is the identifier you are writing on the left side of the assignment expression.
Local variable named "foo"
Class instance variable named "foo"
Quote:
Originally Posted by
nlgootee
I thought that it was the objectname.
The object name is a property of the object provided through its QObject ancestry, similar to how the font is provided through its QWidget ancestry, etc.
Cheers,
_
Re: subclass QLineEdit to have an index
Quote:
Originally Posted by
nlgootee
Cool! Can you do it in python?
I suppose you could allocate a container (an array, list, whatever) that maps integers to QLineEdits. You would fill it with the QLineEdit instances at initialization, and you would define a function named LineEdit that takes an integer i, finds the QLineEdit in the container with index i, and returns it. I do not know much about Python, but it looks like it would let you do LineEdit(i).setText("foo").
Re: subclass QLineEdit to have an index
Quote:
Originally Posted by
anda_skoa
Hmm, I would have assumed you had had a look at some Python tutorial before starting on an actual application.
The name of the variable is the identifier you are writing on the left side of the assignment expression.
Local variable named "foo"
Class instance variable named "foo"
The object name is a property of the object provided through its QObject ancestry, similar to how the font is provided through its QWidget ancestry, etc.
Cheers,
_
In the Qt designer the name that you use to access the object in code is set by the objectname
Re: subclass QLineEdit to have an index
Quote:
Originally Posted by
nlgootee
In the Qt designer the name that you use to access the object in code is set by the objectname
Yes, because Designer has to pick an identifier for the field name in the code it generates. It could choose anything; it just makes sense to choose what the user specified in the objectName property.
However, these are two very different things.
The identifier of the field, like all identifiers in C++, is only present at compile time. E.g. when you write code such as
Code:
myTextEdit->setText("Hello");
the compiler statically knows exactly where to find the pointer myTextEdit, what its type is, etc, and produces machine code that loads the value in this pointer and calls the appropriate method. myTextEdit is an identifier in the source code that does not appear in the executable (unless maybe you compile with debugging support). You could rename this identifier and recompile, and you would probably get the same binary.
In particular, you cannot, at runtime, build a string "myTextEdit" and magically expect the C++ runtime to figure out that there was an identifier with this name in the source, retrieve its location and type, and allow you to use the object. Other languages support this kind of reflexion, but C++ does not. C++ requires you to do things explicitly. OTOH, Python may let you look up a field by its name at runtime.
Qt's meta-object system, among other things, attempts to add a form of reflexion. The objectName property, for instance, attaches a string to each QObject, that you can retrieve at runtime. You can therefore look for a QObject with a specific object name among a set of QObjects. However, you have to explicitly perform this search by calling a function implementing it. This is what the method QObject::findChild() does.
So, you need a lookup mechanism to retrieve a QLineEdit instance based on an index at runtime. What we have been trying to explain since the beginning of this thread is that, in your particular case, instead of using a costly generic mechanism like QObject::findChild() or Python's reflexion, you can simply store the QLineEdits in an array, and retrieve the element at the specified index. In fact, your problem is a textbook example of a situation in which you will naturally use an array. Every serious programming language has arrays, including Python, precisely for situations like this one.
Re: subclass QLineEdit to have an index
Code:
self.swInventory.setObjectName("swInventory")
self.page.setObjectName("page")
self.swInventory.addWidget(self.page)
self.page_2.setObjectName("page_2")
self.swInventory.addWidget(self.page_2)
This is code written by the designer for a stackedwidget. How can I write code like this that will loop and create a variable number of pages if I can't create the identifier names on the fly? The objectName is a string, so that is not a problem. Can I just use the same identifier (self.Page) with a different objectName for each page?
Re: subclass QLineEdit to have an index
Quote:
Originally Posted by
nlgootee
How can I write code like this that will loop and create a variable number of pages if I can't create the identifier names on the fly?
If you want to store the reference to each page then this has been answered at least a dozend times in this thread by now.
Quote:
Originally Posted by
nlgootee
Can I just use the same identifier (self.Page) with a different objectName for each page?
You can reuse a variable as often as you like. Everytime you assign an object reference to it, you can access that object's properties, including setting a different object name.
Obviously that doesn't make the object accessible by that name, but yeye_olive already explained the difference between an identifier and an object specific value.
Cheers,
_
Re: subclass QLineEdit to have an index
Alright, let us go back to basics. Forget QLineEdit, forget Qt. I can restate your problem abstractly as "I need to construct n objects of the same type, and uniquely associate each of them with an integer index in the range 0..n - 1; then, later, someone gives me an index value i in 0..n - 1, that I do not know at compile time, and I need to retrieve the object associated with i."
How would I do that in Python? Python 101: with a list (which is less optimized than an array in this case, but we don't care). Here is a minimal program that illustrates this. It prompts the user to type the value of n, then n integer values, then the value of i. It then prints the ith (counting from 0) integer:
Code:
values = []
n = int(input("Please enter the number of integers: "))
for idx in range(0, n):
val = int(input("Please enter the value of the next integer: "))
values.append(val)
i = int(input("Please enter the index of the integer you want me to print: "))
print(values[i])
That's it. Every basic programming course on data structures must contain a variation of this.
Notice that I use a single variable, val, in the loop that populates the list, to hold the value of each element in turn. I have to do that, that is the whole point of a loop: I write a piece of code that will be executed an unbounded number of times, and I have finally many variables to store the state of each iteration; so, these variables get rewritten over and over. Is that a problem? No, because I use another data structure, the list values, to remember all the successive values of val, along with their index. Later on, I can find the ith element with values[i].
The point is: I do not rely on Python's environment (the mapping of variable names to values) to store all the integers in, say, variables named val0, val1, etc, added on the fly; I explicitly use a data structure for that. The environment is not meant to be used as a data structure.
Now, replace "integer" with "QLineEdit" and you end up with the problem you are trying to solve. So, why don't you do like any first year programming student and add a list/array/whatever to your program, so that we may all move on to real problems?
Re: subclass QLineEdit to have an index
Quote:
Originally Posted by
nlgootee
No, I actually don't need to store them. I will try to explain more clearly how I want this to work. I create a column of 1650 rows that consist of a QLineEdit(call it MyLineEdit(item#)) and 2 or 3 Labels (item#, description, price) the lineedit and labels are indexed with the same number. The salesperson while making an order scrolls down the column and at each item in the order places a number(quantity) in the LineEdit. When the order is complete, the text of the LineEdit and the labels is placed in the invoice and saved in a database and the text is cleared from all of the LineEdits to be ready for the next order. The LineEdits exist on the screen until the application is closed, the text is only there until it is saved in the database. If in the future, someone needs to look at the order, a query is run using the OrderID and the order is recreated placing the quantity of each item in the order in the LineEdits using MyLineEdit(item#).setText(). The LineEdits are created at the beginning of the application and destroyed when it closes, I don't need to store them anywhere. When the order is created, I can use the textChanged signal to store the information and probably don't actually need the item# index, but when the order is recreated being able to use MyLineEdit(item#).setText() is much better than the way it was done in the original application. I hope that this helps to clear thing up. I really appreciate your help with this. Thanks
Hello,
This is my first post in this forum. So please don't mind if any mistakes.
Coming to the problem, as per my understanding in a short way, you have many rows and each row has a line edit where user can enter some value. At last u have to get all the values from all the line edits. And those line edits are dynamically created in a for loop.
I have worked on the similar scenario where i have some buttons which are dynamically created in a for loop and i need to understand on fly which button is triggered.
For this i have used QSignalMapper concept. Below is the sample code.
Code:
//Code Begins
for(int nIndex = 0; nIndex < 10; nIndex++)
{
//create buttons
//set the properties as required.
connect(btn , SIGNAL(clicked()), m_btnSigMapper, SLOT(map()));
//now create unique name for your widget
m_btnSigMapper->setMapping(btn , szMapName);
}
//now this is important connect
//Here we connect to our slot whenever a button is clicked.
connect(m_btnSigMapper,
SIGNAL(mapped
(const QString &)),
this,
SLOT(slotBtnClicked
(const QString &)));
//slotBtnClicked function
void slotBtnClicked
(QString szMapName
) {
//do the functionality based on the map name because it is unique.
}
////// A sample code for your problem statement can be like below.
for(int nIndex = 0; nIndex < 10; nIndex++)
{
//create line edits
//now set a name to your line edit.
lineEdit.
setObjectName(QString("LineEdit").
append(QString::number(nIndex
)));
//set the properties as required.
//Connect textEdited signal.
connect(lineEdit ,
SIGNAL(textEdited
(const QString &)), m_lineEditSigMapper,
SLOT(map
()));
m_lineEditSigMapper->setMapping(lineEdit , lineEdit);
}
//now this is important connect
//Here we connect to our slot whenever a text is edited in your line edits.
connect(m_lineEditSigMapper,
SIGNAL(mapped
(QWidget*)),
this,
SLOT(slotLineEditTextEdited
(QWidget*)));
//Create a variable which stores the values from LineEdits.
QMap<QString,QString> m_lineEditValues; //class variable
//slotLineEditTextEdited function
void slotLineEditTextEdited
(QWidget* widget
) {
QLineEdit *lineEdit
= reinterpret_cast<QLineEdit
*>
(widget
);
m_lineEditValues.insert(lineEdit.objectName(),lineEdit.text());
}
Cheers...
Re: subclass QLineEdit to have an index
Thanks for your input. This looks like something that I could use for a column of pushbuttons, but I really don't translate c++ to python very well, so I will have to work on it.
Added after 4 minutes:
I want to thank everybody that submitted code to this discussion. We have decided to go with a different method but your expertise will not go to waste because the next part of the project absolutely needs a list and I will be able to use what I have learned here. Thanks again.
Re: subclass QLineEdit to have an index
I forgot to mention that the program that I am converting has a column of pushbuttons that I have to deal with, so really, thanks.