Dynamic Handling of Hundreds of UI elements
-
Moderatorswrote on 8 Feb 2016, 13:15 last edited by kshegunov 2 Aug 2016, 14:10
@mrsurge
Hello,
For one you could make Qt do the casting for you:QList<QLineEdit *> list = ui->doubleSpinBox->children<QLineEdit *>(); foreach (QLineEdit * item, list) item->installEventFilter(this);
And then in your event filter you could connect the dialog's
accepted
signal to the line edit:bool MainWindow::eventFilter(QObject * obj, QEvent * event) { if(event->type() == QEvent::MouseButtonPress) { Dialog mdialog; QSignalMapper mapper(&mdialog); mapper.setMapping(qobject_cast<QWidget *>(obj)); QObject::connect(&mdialog, SIGNAL(accepted()), &mapper, SLOT(map())); QObject::connect(&mapper, SIGNAL(mapped(QWidget *)), this, SLOT(saveDataToLineEdit(QWidget *))); mdialog.exec(); } return false; } void MainWindow::saveDataToLineEdit(QWidget * widget) { QLineEdit * lineEdit = qobject_cast<QLineEdit *>(widget); Dialog * dialog = qobject_cast<Dialog *>(sender()->parent()); // ... Transfer data between the dialog and the line edit here ... }
Is this what you were asking for?
Kind regards.
EDIT:
I've moved the mapper to the stack, as it's not necessary to create it with new (since you're using a modal dialog). -
also be sure to check
http://www.qtcentre.org/threads/65146-Dynamic-Handling-of-Hundreds-of-UI-elements -
@mrsurge
Hello,
For one you could make Qt do the casting for you:QList<QLineEdit *> list = ui->doubleSpinBox->children<QLineEdit *>(); foreach (QLineEdit * item, list) item->installEventFilter(this);
And then in your event filter you could connect the dialog's
accepted
signal to the line edit:bool MainWindow::eventFilter(QObject * obj, QEvent * event) { if(event->type() == QEvent::MouseButtonPress) { Dialog mdialog; QSignalMapper mapper(&mdialog); mapper.setMapping(qobject_cast<QWidget *>(obj)); QObject::connect(&mdialog, SIGNAL(accepted()), &mapper, SLOT(map())); QObject::connect(&mapper, SIGNAL(mapped(QWidget *)), this, SLOT(saveDataToLineEdit(QWidget *))); mdialog.exec(); } return false; } void MainWindow::saveDataToLineEdit(QWidget * widget) { QLineEdit * lineEdit = qobject_cast<QLineEdit *>(widget); Dialog * dialog = qobject_cast<Dialog *>(sender()->parent()); // ... Transfer data between the dialog and the line edit here ... }
Is this what you were asking for?
Kind regards.
EDIT:
I've moved the mapper to the stack, as it's not necessary to create it with new (since you're using a modal dialog).wrote on 9 Feb 2016, 05:19 last edited by mrsurge 2 Sept 2016, 05:21QList<QLineEdit *> list = ui->doubleSpinBox->children<QLineEdit *>(); foreach (QLineEdit * item, list) item->installEventFilter(this);
returns
**error: 'QLineEdit' does not refer to a value
QList<QLineEdit > list = ui->doubleSpinBox->children<QLineEdit >();in my compiler. Remember I may be doing something really stupid, I'm new at qt
-
QList<QLineEdit *> list = ui->doubleSpinBox->children<QLineEdit *>(); foreach (QLineEdit * item, list) item->installEventFilter(this);
returns
**error: 'QLineEdit' does not refer to a value
QList<QLineEdit > list = ui->doubleSpinBox->children<QLineEdit >();in my compiler. Remember I may be doing something really stupid, I'm new at qt
@mrsurge
No, the problem is with my code, it happens sometimes when I don't double-check my examples. The proper function to use would beQObject::findChildren
. I usually use it similarly to this:QList<QLineEdit *> list = ui->doubleSpinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly);
This should compile fine.
Kind regards.
-
@mrsurge
No, the problem is with my code, it happens sometimes when I don't double-check my examples. The proper function to use would beQObject::findChildren
. I usually use it similarly to this:QList<QLineEdit *> list = ui->doubleSpinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly);
This should compile fine.
Kind regards.
wrote on 9 Feb 2016, 06:14 last edited by mrsurge 2 Sept 2016, 06:15@kshegunov
your right that did compile just fine, but it only works for doubleSpinBox not doubleSpinBox_2 - doubleSpinBox_312 -
@kshegunov
your right that did compile just fine, but it only works for doubleSpinBox not doubleSpinBox_2 - doubleSpinBox_312Moderatorswrote on 9 Feb 2016, 06:25 last edited by kshegunov 2 Sept 2016, 06:28Just apply the same principle:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QList<QSpinBox *> sbList = findChildren<QSpinBox *>(QString(), Qt::FindDirectChildrenOnly); foreach (QSpinBox * spinBox, sbList) { spinBox->installEventFilter(this); //< Do you need this?? QList<QLineEdit *> leList = spinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly); foreach (QLineEdit * lineEdit, leList) lineEdit->installEventFilter(this); } }
-
Just apply the same principle:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QList<QSpinBox *> sbList = findChildren<QSpinBox *>(QString(), Qt::FindDirectChildrenOnly); foreach (QSpinBox * spinBox, sbList) { spinBox->installEventFilter(this); //< Do you need this?? QList<QLineEdit *> leList = spinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly); foreach (QLineEdit * lineEdit, leList) lineEdit->installEventFilter(this); } }
wrote on 9 Feb 2016, 18:41 last edited by mrsurge 2 Sept 2016, 18:46@kshegunov
This worked :QList<QDoubleSpinBox *> sbList = ui->centralWidget->findChildren<QDoubleSpinBox *>(QString()); foreach (QDoubleSpinBox * spinBox, sbList) { //spinBox->installEventFilter(this); //< Do you need this??//<-no I don't QList<QLineEdit *> leList = spinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly); foreach (QLineEdit * lineEdit, leList) lineEdit->installEventFilter(this); }
many thanks for steering me in the right direction.
now on to saving the item to the specific line item
-
@kshegunov
This worked :QList<QDoubleSpinBox *> sbList = ui->centralWidget->findChildren<QDoubleSpinBox *>(QString()); foreach (QDoubleSpinBox * spinBox, sbList) { //spinBox->installEventFilter(this); //< Do you need this??//<-no I don't QList<QLineEdit *> leList = spinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly); foreach (QLineEdit * lineEdit, leList) lineEdit->installEventFilter(this); }
many thanks for steering me in the right direction.
now on to saving the item to the specific line item
@mrsurge
Yes, of course, I forgot we're in a main window. Anyway, I'm glad it worked. One note, though, if possible use theQObject::findChildren
withQt::FindDirectChildrenOnly
so Qt will not go about recursively looking for all. If your spin boxes are in layouts, but not inside other widgets, this should also work:QList<QDoubleSpinBox *> sbList = ui->centralWidget->findChildren<QDoubleSpinBox *>(QString(), Qt::FindDirectChildrenOnly);
Kind regards.
-
@mrsurge
Yes, of course, I forgot we're in a main window. Anyway, I'm glad it worked. One note, though, if possible use theQObject::findChildren
withQt::FindDirectChildrenOnly
so Qt will not go about recursively looking for all. If your spin boxes are in layouts, but not inside other widgets, this should also work:QList<QDoubleSpinBox *> sbList = ui->centralWidget->findChildren<QDoubleSpinBox *>(QString(), Qt::FindDirectChildrenOnly);
Kind regards.
wrote on 9 Feb 2016, 23:18 last edited byok now how do I return a value from the dialog box to the doubleSpinBox that was clicked?
-
ok now how do I return a value from the dialog box to the doubleSpinBox that was clicked?
@mrsurge
I've provided some guidelines here.
If this is working,QList<QLineEdit *> leList = spinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly);
then the line edit has a
QSpinBox
for a parent. You have the line edit that'd been clicked here:void MainWindow::saveDataToLineEdit(QWidget * widget) { QLineEdit * lineEdit = qobject_cast<QLineEdit *>(widget); // ... Then the line edit parent is ... QSpinBox * spinBox = qobject_cast<QSpinBox *>(lineEdit->parent()); // ... and so on ... }
-
@mrsurge
I've provided some guidelines here.
If this is working,QList<QLineEdit *> leList = spinBox->findChildren<QLineEdit *>(QString(), Qt::FindDirectChildrenOnly);
then the line edit has a
QSpinBox
for a parent. You have the line edit that'd been clicked here:void MainWindow::saveDataToLineEdit(QWidget * widget) { QLineEdit * lineEdit = qobject_cast<QLineEdit *>(widget); // ... Then the line edit parent is ... QSpinBox * spinBox = qobject_cast<QSpinBox *>(lineEdit->parent()); // ... and so on ... }
wrote on 9 Feb 2016, 23:43 last edited by mrsurge 2 Sept 2016, 23:43@kshegunov said:
bool MainWindow::eventFilter(QObject * obj, QEvent * event)
{
if(event->type() == QEvent::MouseButtonPress)
{
Dialog mdialog;QSignalMapper mapper(&mdialog); mapper.setMapping(qobject_cast<QWidget *>(obj)); QObject::connect(&mdialog, SIGNAL(accepted()), &mapper, SLOT(map())); QObject::connect(&mapper, SIGNAL(mapped(QWidget *)), this, SLOT(saveDataToLineEdit(QWidget *))); mdialog.exec(); } return false;
}
my compiler says
mapper.setMapping(qobject_cast<QWidget *>(obj));
requires a second argument
mapper.setMapping(qobject_cast<QWidget *>(obj),0);
works but i have no idea what thats doing
-
@kshegunov said:
bool MainWindow::eventFilter(QObject * obj, QEvent * event)
{
if(event->type() == QEvent::MouseButtonPress)
{
Dialog mdialog;QSignalMapper mapper(&mdialog); mapper.setMapping(qobject_cast<QWidget *>(obj)); QObject::connect(&mdialog, SIGNAL(accepted()), &mapper, SLOT(map())); QObject::connect(&mapper, SIGNAL(mapped(QWidget *)), this, SLOT(saveDataToLineEdit(QWidget *))); mdialog.exec(); } return false;
}
my compiler says
mapper.setMapping(qobject_cast<QWidget *>(obj));
requires a second argument
mapper.setMapping(qobject_cast<QWidget *>(obj),0);
works but i have no idea what thats doing
@mrsurge
Yes, I forgot the sender. That should be:mapper.setMapping(&mdialog, qobject_cast<QWidget *>(obj));
QSignalMapper is a simple utility class to provide mapping of signals without parameters to signals/slots with a single parameter. This is done, because
QDialog::accepted
has no notion of theQLineEdit
that triggers the event filter, so what the line does is simply to remap the signal to a slot that accepts theQLineEdit
object as a parameter.Kind regards.
-
@mrsurge
Yes, I forgot the sender. That should be:mapper.setMapping(&mdialog, qobject_cast<QWidget *>(obj));
QSignalMapper is a simple utility class to provide mapping of signals without parameters to signals/slots with a single parameter. This is done, because
QDialog::accepted
has no notion of theQLineEdit
that triggers the event filter, so what the line does is simply to remap the signal to a slot that accepts theQLineEdit
object as a parameter.Kind regards.
wrote on 13 Feb 2016, 04:03 last edited byOk I have a separate form, cpp, and .h for my dialog, does all this still apply? do i need to add anything to my dialog.cpp or .h?
-
Ok I have a separate form, cpp, and .h for my dialog, does all this still apply? do i need to add anything to my dialog.cpp or .h?
@mrsurge
Hello,Ok I have a separate form, cpp, and .h for my dialog, does all this still apply? do i need to add anything to my dialog.cpp or .h?
It shouldn't matter how you initialize the dialog, provided you call
QDialog::accept()
at the appropriate place, i.e. when a save/ok button is clicked.Kind regards.
12/16