26

I have a MouseArea that I want to start off centered and then have an absolute position once the up/down/left/right keys are pressed. My problem is that I don't know how to clear the anchor on the MouseArea so that I can specify an absolute position:

import QtQuick 2.0
import QtQuick.Window 2.0

Window {
    id: screen
    width: 360
    height: 360
    visible: true

    Rectangle {
        anchors.fill: parent

        states: [
            State {
                name: "moved"
                AnchorChanges {
                    target: mouseArea
                    anchors.bottom: undefined
                    anchors.left: undefined
                    anchors.right: undefined
                    anchors.top: undefined
                }
            }
        ]

        MouseArea {
            id: mouseArea
            anchors.centerIn: parent
            width: 250
            height: 250
            focus: true
            onClicked: console.log("clicked!")
            onPositionChanged: console.log("position changed!")

            function moveMouseArea(x, y) {
                mouseArea.x += x;
                mouseArea.y += y;
                mouseArea.state = "moved";
                mouseAreaPosText.text = 'Mouse area was moved... new pos: '
                    + mouseArea.x + ', ' + mouseArea.y;
            }

            Keys.onPressed: {
                if (event.key === Qt.Key_Up)
                    moveMouseArea(0, -1);
                if (event.key === Qt.Key_Down)
                    moveMouseArea(0, 1);
                if (event.key === Qt.Key_Left)
                    moveMouseArea(-1, 0);
                if (event.key === Qt.Key_Right)
                    moveMouseArea(1, 0);
            }

            Rectangle {
                anchors.fill: parent
                border.width: 2
                border.color: "black"
                color: "transparent"
            }

            Text {
                id: mouseAreaPosText
                anchors.centerIn: parent
            }
        }
    }
}

At first I just tried setting mouseArea.anchors to undefined but got an error about anchors being a read-only property. I then discovered AnchorChanges, but I can't find a way to remove/clear the anchor; setting anchors.bottom etc. to undefined doesn't work.

Mitch
  • 23,716
  • 9
  • 83
  • 122
  • 2
    Docs (http://qt-project.org/doc/qt-4.8/qml-anchor-layout.html) said "If you wish to change from using anchor-based to absolute positioning, you can clear an anchor value by setting it to `undefined`". – sergk Jun 03 '12 at 22:50

2 Answers2

27

According to docs, setting an anchor attribute to undefined should work. I don't quite get why AnchorChanges did not allow to set anchors.centerIn, but you can workaround it in your moveMouseArea function:

function moveMouseArea(x, y) {
    mouseArea.anchors.centerIn = undefined; // <-- reset anchor before state change
    mouseArea.pos.x += x;
    mouseArea.pos.y += y;
    mouseArea.state = "moved";
    mouseAreaPosText.text = 'Mouse area was moved... new pos: '
        + mouseArea.pos.x + ', ' + mouseArea.pos.y;
}
sergk
  • 3,591
  • 1
  • 20
  • 14
1

Thanks for your help guys. I have found that setting undefined within a state works (if by works you mean only that it doesn't give errors), however once the element moves to yet another state, the anchors magically (and very frustratingly) return. This happens EVEN if you set all anchors undefined in the final state. As mentioned above however, setting undefined in the function before changing state works great. In my case, I set it in my mouseArea in onPressed.

                onPressed: {
                plotWindow04Frame.anchors.bottom = undefined
                plotWindow04Frame.anchors.left = undefined
                plotWindow04Frame.state = "inDrag"
            }

I found it was not necessary to mention the anchor in the onReleased, just the next state. onReleased: { plotWindow04Frame.state = "dropped" }

Also, I should mention, that the final "dropped" state does not mention anchors either, just opacity.

    states: [
    State {
        name: "inDrag"
        PropertyChanges {
            target: plotWindow04Frame
            opacity: .5
        }
    },
    State {
        name: "dropped"
        PropertyChanges {
            target: plotWindow04Frame
            opacity: 1
        }
    }

 ]

    transitions: Transition {
        NumberAnimation { properties: "opacity"; duration:200 }
    }
}

(The idea here was that these plot windows would become translucent (opacity: 0.5) while dragging, but return to opaque (opacity: 1) when the user drops them)

What is nice is that the plotwindow "rectangles" are initially anchored to the bottom of the GUI, but once the user picks them up, they can put them where ever they like.