<snip, set custom property in "onChildrenChanged">
Yes, it should work <snip>
Yes, it works, it was my error. What I'm doing is a little
more complicated, and there was enough obfuscation
for me to confuse myself. ;-)
I now have something that "works", but I want to get
opinions on whether my solution is "stupid" or "best practice".
After further investigation, here's what's going on:
- I create a "myParent" Item{}
- I create "child" items that are not yet parented to my "myParent"
- I explicitly parent the child items with "{ parent: myParent }"
The above works. My confusion was based on:
- the "child" items have application-specific properties
to be set when re-parented (e.g., layout attributes)
- the "myParent" had *additional* (hard-coded) children,
like background rendering, that do not have the
application-specific properties of these "transient"
children.
Because my "onChildrenChanged()" in "myParent"
merely iterated all its children, it attempted to access
application-specific attributes in the "hard-coded"
children (when it should have only accessed those
attributes in the transient children).
Because QML is typesafe, these failed accesses
on the hard-coded children triggered an exception.
IMHO, this is "good" (I am pleased QML provides this
safety -- it backs me up in my design decisions).
QUESTION: What is the preferred mechanism to
"test" children for type, or for "id:", or any distinguishing
characteristic?
For example, my solution is to "test" for my application-
specific attribute, at which point I "conclude" this is
a transient child:
Item {
id: myParent
onChildrenChanged: {
for(var i = 0; i < myParent.children.length; ++i) {
if(myParent.children[i].myApplicationSpecificAttribute === undefined) {
// Not transient child
} else {
// Is transient child
myParent.children[i].myApplicationSpecificAttribute = 1.0;
}
}
}
}
This works. However, I wanted to "see" what was in the child
to understand what I could work with, so I printed it out:
...inserting this snippet to inspect each child...
for (var myKey in myParent.children[i]) {
console.log("child[" + myKey + "] == (" +
mySdGlobe.children[i][myKey] + ")");
}
...I get something like:
-----------------------------------------
child[childrenChanged] == ([object Object])
child[scaleChanged] == ([object Object])
child[heightChanged] == ([object Object])
child[deleteLater] == ([object Object])
child[colorChanged] == ([object Object])
child[yChanged] == ([object Object])
child[gradient] == (null)
child[state] == ()
child[top] == (QVariant(QDeclarativeAnchorLine))
child[opacityChanged] == ([object Object])
child[smooth] == (false)
child[width] == (0)
child[visible] == (true)
child[visibleChanged] == ([object Object])
child[rotationChanged] == ([object Object])
child[transitions] == ([object Object])
child[childrenRectChanged] == ([object Object])
child[data] == ([object Object])
child[clip] == (false)
child[resources] == ([object Object])
child[anchors] == (QDeclarativeAnchors(0x60382b8))
child[right] == (QVariant(QDeclarativeAnchorLine))
child[parent] == (QDeclarativeItem(0x5ef5850))
child[verticalCenter] == (QVariant(QDeclarativeAnchorLine))
child[xChanged] == ([object Object])
child[pos] == ([object Object])
child[myDoubleChanged] == ([object Object])
child[focus] == (false)
child[activeFocusChanged] == ([object Object])
child[states] == ([object Object])
child[color] == (#ffffff)
child[baselineOffset] == (0)
child[updateMicroFocus] == ([object Object])
child[horizontalCenter] == (QVariant(QDeclarativeAnchorLine))
child[myDouble] == (0) <=========MY APPLICATION-SPECIFIC ATTRIBUTE
child[bottom] == (QVariant(QDeclarativeAnchorLine))
child[mapFromItem] == ([object Object])
child[border] == (QDeclarativePen(0x6040890))
child[forceActiveFocus] == ([object Object])
child[baselineOffsetChanged] == ([object Object])
child[baseline] == (QVariant(QDeclarativeAnchorLine))
child[transformOriginPoint] == ([object Object])
child[scale] == (1)
child[left] == (QVariant(QDeclarativeAnchorLine))
child[parentChanged] == ([object Object])
child[transformOriginChanged] == ([object Object])
child[radiusChanged] == ([object Object])
child[activeFocus] == (false)
child[childrenRect] == ([object Object])
child[enabledChanged] == ([object Object])
child[effect] == (null)
child[children] == ([object Object])
child[opacity] == (1)
child[rotation] == (0)
child[zChanged] == ([object Object])
child[clipChanged] == ([object Object])
child[focusChanged] == ([object Object])
child[childAt] == ([object Object])
child[mapToItem] == ([object Object])
child[transform] == ([object Object])
child[transformOrigin] == (4)
child[smoothChanged] == ([object Object])
child[objectName] == ()
child[x] == (0)
child[enabled] == (true)
child[y] == (0)
child[z] == (0)
child[widthChanged] == ([object Object])
child[stateChanged] == ([object Object])
child[height] == (0)
child[radius] == (0)
-----------------------------------------
Good stuff. I can see exactly what's going on.
I don't want to dig too deeply into QML internals (I assume some
of these keys may change), but I was looking for an "id:" field to
uniquely identify the object, and didn't find it (and the "objectName"
field is empty, so I assume that is for different purposes).
I'm sure there are a zillion options. For example, I could
create a "myType" field to define my own types, check
for specific fields like I'm doing, or come up with other
heuristics (for example, in my debugging, I uniquely identified
objects by setting universally unique values to "height").
However, I was curious if there was a "preferred/best-practice"
method, since I ASSUME this is a COMMON case:
?COMMON_CASE: Rich application-specific QML element
with (hard-coded) internal children, but which *also* manages
transient (child) elements that are periodically re-parented
among different QML elements.
For example, this is the common case for any QML element
that performs layout upon its children. Because QML is
OUTSTANDING for such dynamic re-parenting (through
its use of states and transitions), I'd assume many applications
want to iterate "transient" children separate from "hard-coded"
children.
SUMMARY QUESTION: What is best practice to separately iterate
"transient" children from "hard-coded" children?
Thanks!
--charley