Wrong coordinates white getting real position of item relative to its parent

后端 未结 2 1517
逝去的感伤
逝去的感伤 2021-01-19 18:50

I have simple scene with only 2 Rectangles. The difference is that first one uses absolute coordinates and second one uses anchors. In this case bo

相关标签:
2条回答
  • 2021-01-19 19:11

    Both rectangles have same coordinates but on different time:

    import QtQuick 2.4
    import QtQuick.Window 2.2
    
    Window {
        visible: true
        width: 600
        height: 600
        Rectangle {
            id: rec1
            x: 200
            y: 200
            width: 200
            height: 200
            color: "green"
            opacity: 0.5
            Component.onCompleted: console.log("rec1: " + rec1.x + "," + rec1.y);
        }
    
        Rectangle {
            id: rec2
            anchors.centerIn: parent
            width: 200
            height: 200
            color: "blue"
            opacity: 0.5
            Component.onCompleted: console.log("rec2: " + rec2.x + "," + rec2.y);
            onXChanged: console.log("rec2.x: " + rec2.x);
            onYChanged: console.log("rec2.y: " + rec2.y);
        }
    }
    
    0 讨论(0)
  • 2021-01-19 19:32

    The documentation of Item proposes the mapToItem function:

    Maps the point (x, y) or rect (x, y, width, height), which is in this item's coordinate system, to item's coordinate system, and returns an object with x and y (and optionally width and height) properties matching the mapped coordinate.

    If item is a null value, this maps the point or rect to the coordinate system of the root QML view.

    Since the coordinate must be in item' system, the correct way to call the function in your case would be:

    <item_id>.mapToItem(<parent_id>, 0, 0)
    

    where (0, 0) is the origin of <item_id> coordinates system.

    Since in this case the parent is not an Item itself, we can exploit the null version of the method described by documentation and write:

    <item_id>.mapToItem(null, 0, 0)
    

    That's the theory. However, in this particular case (as noted by others), the layout management has not set the coordinate properties yet and thus the methods fail. That seems to be related to the non-consistent state in which items fall during initialisation. Indeed, if we use the function in the onDestruction handler, i.e. when we are sure that initialisation has finished, they give the expected results. See your modified code below:

    import QtQuick 2.4
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.3
    
    Window  {
        visible: true
        width: 600
        height: 600
    
        Rectangle {
            id: rec1
            x: 200
            y: 200
            width: 200
            height: 200
            color: "green"
            opacity: 0.5
        }
    
        Rectangle {
            id: rec2
            width: 200
            height: 200
            anchors.centerIn: parent
    
            color: "blue"
            opacity: 0.5
        }
    
        Component.onCompleted: {
            console.info("NOPE! :(")
            var cords = rec1.mapToItem(null, 0, 0)
            console.info("rec1: " + cords.x + "  " + cords.y)
            cords = rec2.mapToItem(null, 0, 0)
            console.info("rec2: " + cords.x + "  " + cords.y)
        }
    
        Component.onDestruction: {
            console.info("YES! :)")
            var cords = rec1.mapToItem(null, 0, 0)
            console.info("rec1: " + cords.x + "  " + cords.y)
            cords = rec2.mapToItem(null, 0, 0)
            console.info("rec2: " + cords.x + "  " + cords.y)
            cords = rec2.mapToItem(null, 100, 100)      // (100, 100) of second rec is...
            console.info("rec2: " + cords.x + "  " + cords.y)   // correctly (300, 300)  !!
        }
    }
    

    Output:

    qml: NOPE! :(
    qml: rec1: 200  200
    qml: rec2: -100  -100
    qml: YES! :)
    qml: rec1: 200  200
    qml: rec2: 200  200
    qml: rec2: 300  300
    
    0 讨论(0)
提交回复
热议问题