PDA

View Full Version : QObject::findChildren() strange behavior



folibis
2nd December 2013, 00:48
In my program I have QDialog to edit configuration options and it is empty as program start.
I use QPlugin modules so each module can add its own panel to this dialog. Base class of such panel is:

class ConfigWidget : public QWidget
{
public:
explicit ConfigWidget(QWidget *parent = 0) : QWidget(parent){}
virtual void SetValues(){}
virtual void SaveValues(){}
};
And the code of accept() signal of this dialog:

void ConfigDialog::okClicked()
{
QList<ConfigWidget *> widgets = findChildren<ConfigWidget *>();
foreach(ConfigWidget * widget,widgets)
{
widget->SaveValues();
}
Config::instance()->SaveConfig();
accept();
}
I just get all the panels and save its values. I guess it is very simple and clear.
But findChildren returns all the widgets of dialog - buttons, lineedits etc. And it is very very strange for me.
From docs: Returns all children of this object with the given name that can be cast to type T
How QPushButton can be cast to ConfigWidget?? QPushButton have no SaveValues() function so I am very disappointed here ...
And, if it is expected result of findChildren(), how can I get only widgets derived from ConfigWidget?

ChrisW67
2nd December 2013, 01:40
Add the Q_OBJECT macro to your ConfigDialog class and rerun qmake to ensure that it gets run through moc. Without this macro there is no QObject runtime data for this class, so you get the underlying QWidget data. All widgets can be cast to QWidget.

folibis
2nd December 2013, 02:59
Thanks, ChrisW67, it works!

anda_skoa
2nd December 2013, 09:06
If your plugins can create ConfigWidget* you might have access to them at creation time at some point. In that case storing them in a QList<ConfigWidget*> would be more efficient, since you don't have to traverse the whole widget tree, nor need any casting.

Cheers,
_