0

I have an Item, that should draw itself always relative to another Item (without anchoring, as they might not be siblings or parent->child. For this I use the mapFromItem-method inherit to every Item-desecendent.

import QtQuick 2.0

Rectangle {
    id: root
    property Item origin
    property point originPosition: parent.mapFromItem(origin, origin.width / 2, origin.height / 2)

    width: 10
    height: 10
    color: 'red'
    x: originPosition.x - 5
    y: originPosition.y - 5
}

This works fine, as long as I don't use anchors for layouting, but only x and y as it might be, that the function parent.mapFromItem(...) is being called, befor the position of origin is calculated, and won't get updated as the arguments themselves are not changed.

I already thought: Well, then "let them change!" and modified the call to:

property point originPosition: parent.mapFromitem(origin.parent, origin.x, origin.y)

In the hope that it is updated now. Seemd to work, until another layer that was also anchored was introduced:

Item {
    id: root
    width: 800
    height: 800
    Item {
        width: 400
        height: 400
        anchors.centerIn: parent
        Item {
            id: myOrigin
            width: 100
            height: 100
            anchors.right: parent.right
            anchors.bottom: parent.bottom
        }
    }
}

Now I get the the update of the position of myOrigin within it's parent. But it's parent might not be at the right position and I won't get this update, which breaks everything again.

How can I get this running?

// EDIT: Of course it does break aswell, if the position of one of the parents is changed during runtime, e.g. by an Animation, which should be solved with the same method, I think.

  • I was to fixated on the `anchor`-issue so [this](http://stackoverflow.com/questions/17927714/qml-tracking-global-position-of-a-component) slipped my attention. There are some very similar, and some other interesting solutions, that include traversing the tree to bind to the signals (Would need to be unbound if tree changes) or some global flags (tracked object needs to know of this tracking), and one where a `TrackerObject` is created. A combination of those might be interesting/doable as a C++-implementation. – derM - not here for BOT dreams Apr 28 '17 at 16:58

1 Answers1

0

I ended up writing a small JS function, that does the mapping for me. For this I crawl up the object tree until the root node adding up the coordinates, to find the absolute position of the origin on the root object.

Then I do the crawling from this back to the root object, subtracting the coordinates, to make the result relative to this

function map(itm, cord) {
    var c = itm[cord]
    for (; itm.parent !== null; itm = itm.parent) {
        console.log(itm, c)
        c += itm[cord]
    }
    itm = this.parent
    for (; itm.parent !== null; itm = itm.parent) {
        console.log(itm, c)
        c -= itm[cord]
    }
    return c
}

In my example this would look like this:

import QtQuick 2.7
Rectangle {
    width: 20
    height: 20
    color: 'green'

    x: map(origin, 'x')
    y: map(origin, 'y')

    property Item origin

    function map(itm, cord) {
        var c = itm[cord]
        for (; itm.parent !== null; itm = itm.parent) {
            console.log(itm, c)
            c += itm[cord]
        }
        itm = this.parent
        for (; itm.parent !== null; itm = itm.parent) {
            console.log(itm, c)
            c -= itm[cord]
        }
        return c
    }
}

This seems to work well, at least for shallow object trees.