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). -
also be sure to check
http://www.qtcentre.org/threads/65146-Dynamic-Handling-of-Hundreds-of-UI-elements -
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.
-
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); } }
-
@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
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 ... }
-
@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
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.