Reputation: 12874
Let's say I have 2 types of custom elements — Parent and Child.
And there can be more than one Parent in the scene.
A simple scene looks like this:
Parent {
Child {
id: child1
}
Child {
id: child2
}
}
After the scene is loaded, I want to initialize all the Children in Parent class:
void InitializeChildren() {
list = findChildren<Child*>(QString(),Qt::FindChildrenRecursively);
foreach(Child * child,list) {
InitChild(this,child);
}
But it fails with a more complicated scene:
Parent {
Rectangle {
Repeater {
model: 10
delegate: Child {
}
}
}
}
Just because the Repeater has no Child objects as children.
How can I get all Child's objects if I know exactly that they are nested children of the specified Parent?
Upvotes: 3
Views: 2128
Reputation: 515
There was a change in Qt5 which makes using findChildren()
for Repeater
children not usable anymore. After having a look at qquickrepeater.cpp
, it turns out that the Repeater
calls QQuickItem::setParentItem()
to the children delegates that get created. Thus, the original parents and children remain untouched, but the "visual" parent is the parent of the Repeater.
TLDR:
Do not use findChildren()
in Qt5 to browse through the item scene graph. Instead, use something like the following:
void getAllSearchTypes(QQuickItem *parent, QList<SearchType *> &list) {
QList<QQuickItem *> children = parent->childItems();
foreach (QQuickItem *item, children) {
SearchType *searchObject = dynamic_cast<SearchType *>(item);
if (seachObject) list.append(searchObject);
// call recursively and browse through the whole scene graph
getAllSearchTypes(item, list);
}
}
And call the function like that:
QList<SearchType *> list;
getAllSearchTypes(rootItem, list);
// list now contains all objects of type SearchType, recursively searched children of rootItem
Replace SearchType
with the C++ type you are looking for.
NOTE: the relevant change to findChildren()
, is that you need to call childItems()
and not children()
. Ideally, there would be a template function in QQuickItem
for example called findChildItems()
in future Qt versions, which does the above recursive search internally.
Upvotes: 3
Reputation: 1538
Instead of parsing the repeater you can set the model in you c++ code:
Parent {
Rectangle {
Repeater {
model: childModel
delegate: Child {
Text { text: childValue }
}
}
}
}
In your c++:
QList<QObject*> m_childModel;
void InitializeChildren() {
this->m_childModel.append(new Child("value 1"));
this->m_childModel.append(new Child("value 2"));
this->m_scene->rootContext()->setContextProperty("childModel", QVariant::fromValue(m_childModel));
}
you also need to do the setContextProperty
before loading the root QML file.
And the Child
declaration:
class Child : public QObject
{
Q_OBJECT
public:
Child(QString value) : m_value(value) {}
Q_PROPERTY(QString childValue READ getChildValue WRITE setChildValue NOTIFY childValueUpdated)
// Other properties...
QString getChildValue() const { return m_value; }
void setChildValue(const QString &value)
{
if (value == m_value)
return;
m_value = value;
emit childValueUpdated();
}
signals:
void childValueUpdated();
private:
QString m_value;
}
Upvotes: 0