Creating vector of QLineEdit and connect signal for each one
-
Hello. In my program I have a QSpinBox and depending on the value of the spinbox, I must dynamically create a number of QLabel and QLineEdit equal to the value of the QSpinBox.
I have managed to do that just fine:
In the MainWindow.h I have declared the vectors:
QVector <QLabel*> cell_label; QVector <QLineEdit*> cell_edit;
In my Mainwindow.cpp:
void MainWindow::on_spinBox_valueChanged(int arg1) { clearLayout(ui->test_grid); // clear the grid layout to ensure all previous widgets are deleted cell_label.clear(); //clear the label vector cell_edit.clear(); //clear the edit vector for(int i =0;i<arg1;i++){ QString cell_name = "Cell " + QString::number(i); cell_label.append(new QLabel(cell_name,this)); cell_edit.append(new QLineEdit("Unknown",this)); if(i >6){ ui->test_grid->addWidget(cell_label[i],i-7,2); ui->test_grid->addWidget(cell_edit[i],i-7,3); } else{ ui->test_grid->addWidget(cell_label[i],i,0); ui->test_grid->addWidget(cell_edit[i],i,1); } } }
And that seems to work fine:
My problem:
Everytime the QLineEdit text is changed, I want to change its color depending on the text. If I didint have a vector of QLineEdits, that would be very simple. I could just simple create a textChanged signal such as:connect(cell_edit[i], &QLineEdit::textChanged, this, &MainWindow::cell_text_changed);
But the problem I have with the above method is that there is no way of knowing which particular QLineEdit has been modified. As you can see from the image above, I have 7 different QLineEdit that bas been created and if I modify the QLineEdit of Cell 2, I need to know that Cell 2 has been modified and not something else.
textChanged signal only takes text value as a parameter but it does not take the actual QLineEdit widget as an additional parameter.In the cell_text_changed function I need to know 2 things:
- The text
- Which QLineEdit widget triggered the function.
I would appreciate if someone could suggest what would be the best way to solve this.
-
Hello. In my program I have a QSpinBox and depending on the value of the spinbox, I must dynamically create a number of QLabel and QLineEdit equal to the value of the QSpinBox.
I have managed to do that just fine:
In the MainWindow.h I have declared the vectors:
QVector <QLabel*> cell_label; QVector <QLineEdit*> cell_edit;
In my Mainwindow.cpp:
void MainWindow::on_spinBox_valueChanged(int arg1) { clearLayout(ui->test_grid); // clear the grid layout to ensure all previous widgets are deleted cell_label.clear(); //clear the label vector cell_edit.clear(); //clear the edit vector for(int i =0;i<arg1;i++){ QString cell_name = "Cell " + QString::number(i); cell_label.append(new QLabel(cell_name,this)); cell_edit.append(new QLineEdit("Unknown",this)); if(i >6){ ui->test_grid->addWidget(cell_label[i],i-7,2); ui->test_grid->addWidget(cell_edit[i],i-7,3); } else{ ui->test_grid->addWidget(cell_label[i],i,0); ui->test_grid->addWidget(cell_edit[i],i,1); } } }
And that seems to work fine:
My problem:
Everytime the QLineEdit text is changed, I want to change its color depending on the text. If I didint have a vector of QLineEdits, that would be very simple. I could just simple create a textChanged signal such as:connect(cell_edit[i], &QLineEdit::textChanged, this, &MainWindow::cell_text_changed);
But the problem I have with the above method is that there is no way of knowing which particular QLineEdit has been modified. As you can see from the image above, I have 7 different QLineEdit that bas been created and if I modify the QLineEdit of Cell 2, I need to know that Cell 2 has been modified and not something else.
textChanged signal only takes text value as a parameter but it does not take the actual QLineEdit widget as an additional parameter.In the cell_text_changed function I need to know 2 things:
- The text
- Which QLineEdit widget triggered the function.
I would appreciate if someone could suggest what would be the best way to solve this.
@lukutis222
This question is asked often as it is a common requirement. The (modern) answer is to specify a C++ lambda for the slot, which allows you to pass necessary parameters from where theconnect()
is specified:connect(cell_edit[i], &QLineEdit::textChanged, this, [this, i]() { cell_text_changed(i); ); // or connect(cell_edit[i], &QLineEdit::textChanged, this, [this, i](const QString &text) { cell_text_changed(i, text); ); // or connect(cell_edit[i], &QLineEdit::textChanged, this, [this, i](const QString &text) { cell_text_changed(cell_edit[i], text); );
-
@lukutis222
This question is asked often as it is a common requirement. The (modern) answer is to specify a C++ lambda for the slot, which allows you to pass necessary parameters from where theconnect()
is specified:connect(cell_edit[i], &QLineEdit::textChanged, this, [this, i]() { cell_text_changed(i); ); // or connect(cell_edit[i], &QLineEdit::textChanged, this, [this, i](const QString &text) { cell_text_changed(i, text); ); // or connect(cell_edit[i], &QLineEdit::textChanged, this, [this, i](const QString &text) { cell_text_changed(cell_edit[i], text); );
Thanks! That works like a charm. I used:
connect(cell_edit[i], &QLineEdit::textChanged, this, [this, i](const QString &text) { cell_text_changed(text,cell_edit[i]);} );
To the function I pass the text and the QLineEdit widget
void MainWindow::cell_text_changed(const QString &arg1,QLineEdit* line_edit) { qDebug("cell tect changed = %s",arg1.toStdString().c_str()); if(strcmp(arg1.toStdString().c_str(),"Connected")==0){ qDebug("connected detected"); line_edit->setStyleSheet("QLineEdit { background-color: rgb(0, 255, 0); selection-background-color: rgb(233, 99, 0); }"); } }
Although I must say that I am not familiar at all with such syntax. I have never come across something like that before. Would you be able to suggest some reading material regarding this?
-
Thanks! That works like a charm. I used:
connect(cell_edit[i], &QLineEdit::textChanged, this, [this, i](const QString &text) { cell_text_changed(text,cell_edit[i]);} );
To the function I pass the text and the QLineEdit widget
void MainWindow::cell_text_changed(const QString &arg1,QLineEdit* line_edit) { qDebug("cell tect changed = %s",arg1.toStdString().c_str()); if(strcmp(arg1.toStdString().c_str(),"Connected")==0){ qDebug("connected detected"); line_edit->setStyleSheet("QLineEdit { background-color: rgb(0, 255, 0); selection-background-color: rgb(233, 99, 0); }"); } }
Although I must say that I am not familiar at all with such syntax. I have never come across something like that before. Would you be able to suggest some reading material regarding this?
@lukutis222
Search forlambda
in https://wiki.qt.io/New_Signal_Slot_Syntax and in https://doc.qt.io/qt-6/signalsandslots.html. For C++ lambdas themselves see https://en.cppreference.com/w/cpp/language/lambda.Lambdas were added in C++ 11 and have since become "common", as in other languages. Once you have got over the syntax etc. they are very useful!
On a separate topic. Why in your
cell_text_changed()
are you usingtoStdString()
andstrcmp()
? Quite unnecessary (and we rarely use C functions likestrcmp()
any longer). Simply:qDebug("cell text changed = %s",arg1); // or qDebug() << "cell text changed =" << arg1; if(arg1 == "Connected"){
-
@lukutis222
Search forlambda
in https://wiki.qt.io/New_Signal_Slot_Syntax and in https://doc.qt.io/qt-6/signalsandslots.html. For C++ lambdas themselves see https://en.cppreference.com/w/cpp/language/lambda.Lambdas were added in C++ 11 and have since become "common", as in other languages. Once you have got over the syntax etc. they are very useful!
On a separate topic. Why in your
cell_text_changed()
are you usingtoStdString()
andstrcmp()
? Quite unnecessary (and we rarely use C functions likestrcmp()
any longer). Simply:qDebug("cell text changed = %s",arg1); // or qDebug() << "cell text changed =" << arg1; if(arg1 == "Connected"){
@JonB
Thanks for reading material suggestions. And thanks for noticing my string comparison. I have replaced them now with more clean looking and simple solution that you have suggested.I used strcmp because I come from C background. Most C++ features are still new to me.
-
@JonB
Thanks for reading material suggestions. And thanks for noticing my string comparison. I have replaced them now with more clean looking and simple solution that you have suggested.I used strcmp because I come from C background. Most C++ features are still new to me.
@lukutis222 said in Creating vector of QLineEdit and connect signal for each one:
I used strcmp because I come from C background. Most C++ features are still new to me.
So did I :) But these days there are better C++ (inbuilt,
std::
or Qt) alternatives to nearly every function which we used to use from the C runtime library.