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 item.qml
and I have no idea why?
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.
EDIT 1:
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
inside ToggleAbleItem.qml
and then I tried it also on main.qml
CodePudding user response:
So it is basically a matter of binding evaluation. When the ToggleableItem
is created and the absolutePosition
property is evaluated the positioning of the item has not been done yet and because the bound statement isn't connected to any geometry property of the Item that would trigger a reevaluation the property keeps its initial value of (0,0).
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.
The other solution would be to create a function absolutePositionFunc()
which gets called after the positioning is done whenever you need to get the absolute position.
import QtQuick
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Item {
id: rootToggle
anchors.fill: parent
Column {
ToggleableItem {
id: toggleItem1
rootItem: rootToggle
color: "red"
Component.onCompleted: console.log("toggle item #1", toggleItem1.mapToItem(rootToggle, 0, 0))
}
ToggleableItem {
id: toggleItem2
rootItem: rootToggle
color: "green"
Component.onCompleted: console.log("toggle item #2", toggleItem2.mapToItem(rootToggle, 0, 0))
}
onPositioningComplete: {
console.log(toggleItem1.absolutePosition,
toggleItem1.absoultePositionFunc())
console.log(toggleItem2.absolutePosition,
toggleItem2.absoultePositionFunc())
}
}
}
}
ToggleableItem.qml
import QtQuick
Rectangle {
id: toggleableItem
required property Item rootItem
readonly property point absolutePosition: {
toggleableItem.y // geometric property in binding to trigger re-evaluation
return toggleableItem.mapToItem(toggleableItem.rootItem, 0, 0)
}
function absolutePositionFunc() {
return toggleableItem.mapToItem(toggleableItem.rootItem, 0, 0)
}
width: 100
height: 40
Component.onCompleted: console.log("absoulte position",
toggleableItem.absolutePosition)
}
CodePudding user response:
Have a look at my comments on your question. This is the solution using the parent
property. Again, don't use ids across different files.
import QtQuick
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Item {
id: rootToggle
anchors.fill: parent
ToggleableItem {
id: secondToggleItem
x: 50
y: 50
Text {
text: "text2"
color: "blue"
font.pixelSize: 24
}
Component.onCompleted: console.log(secondToggleItem.mapToItem(rootToggle, 0, 0))
}
}
}
ToggleableItem.qml
import QtQuick
Item {
id: idToggleableItem
implicitHeight: childrenRect.height
implicitWidth: childrenRect.width
readonly property point absolutePosition: idToggleableItem.mapToItem(parent, 0, 0)
Component.onCompleted: console.log(idToggleableItem.absolutePosition)
}
CodePudding user response:
I had to assign the value after completion inside the Component.onCompleted()
function and then the value is no more 0. I also choosed the mapFromItem()
function instead of the mapToItem()
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!