How to use mapToItem inside my Custom Item? (QML, Qt)
-
I am trying to use the maptoItem() function, it works when I use it inside the
main.qml
but not when used directly inside my custom ItemToggleAbleItem.qml
and I have no idea why? EveryToggleAbleItem.qml
should safe his absolute position( to the idroot
specified).main.qml
Item{ id:root_toggle width: parent.width height: parent.height //... code here Column Item etc that changes the y,x position of ToggleAbleItem ToggleAbleItem{ id:second_toggle_item Text { id:fsdfsd text: "text2" color: "blue" font.pixelSize: 24 } Component.onCompleted: { var l = second_toggle_item.mapToItem(root_toggle, 0, 0) console.log(l) } } } //... code here
Console log correctly prints
[debug] expression for onCompleted (qrc:/main.qml:182) - QPointF(0, 42)
ToggleAbleItem.qml
Item{ id: id_toggleable_item implicitHeight: childrenRect.height implicitWidth: childrenRect.width readonly property point absolute_position: id_toggleable_item.mapToItem(root_toggle, 0, 0) Component.onCompleted: { console.log(absolute_position) } }
Console log prints wrong values
[debug] expression for onCompleted (qrc:/ToggleFunctionality/ToggleAbleItem.qml:53) - QPointF(0, 0)
Can someone explain to me why it is mapping one time correctly and the other time not?
I used the exact same item and id.
The goal is not to use
parent
since it can be the 6th child etc...I have also tried to set
property Item my_root_item: root_toggle
insideToggleAbleItem.qml
and then I tried it also onmain.qml
any advice?
-
"One solution would be to add the toggleableItem.y in front of the binding expression so that the binding is always reevaluated if the y property changes. Basically, make the binding dependent on a geometric property that changes when the item is re-positioned."
readonly property point absolutePosition: { toggleableItem.y // geometric property in binding to trigger re-evaluation return toggleableItem.mapToItem(toggleableItem.rootItem, 0, 0) }
-
I had to assign the value after completion inside the
Component.onCompleted()
function and then the value is no more 0. I also choosed themapFromItem()
function instead of themapToItem()
and called it from the root.Component.onCompleted: { absolute_position = root_toggle.mapFromItem(id_toggleable_item, childrenRect.x, childrenRect.y); }
I know it works but If anybody has an explanation for this so I can finally fully understand QML I would still be grateful!
-
Try adding a button you press to do this. The reason is because it can take a bit of time for the Items to finish being created. The property is also not being updated by a variable that is changing. So you have to know the objects exist and are setup before calling this. Doing so during Component.onCompleted could be an issue if not all objects are setup. Also doing this in a property can be a problem because it will evaluate once and not update unless a variable in referenced to trigger an update. So it might work or might not. Depending upon when the property is first evaluated.
-
One thing that might be helpful:
Item { id: root Item { id: item1 Component.onCompleted: { // root item and item2 may not be ready yet } } Item { id: item2 Component.onCompleted: { // root item may not be ready yet, not sure if item1 is ready or not at this point } } Component.onCompleted: { // I "think" all items in root item are setup at this point. } }
I think an Item is setup when all its children are setup. So I think it is fairly safe to do things in the outer Items onCompleted event.
-
"One solution would be to add the toggleableItem.y in front of the binding expression so that the binding is always reevaluated if the y property changes. Basically, make the binding dependent on a geometric property that changes when the item is re-positioned."
readonly property point absolutePosition: { toggleableItem.y // geometric property in binding to trigger re-evaluation return toggleableItem.mapToItem(toggleableItem.rootItem, 0, 0) }