Search code examples
qtqmlqtquick2qquickitem

How to pan a QML item on MouseArea drag


I have a Qt app which runs on iOS and OSX using Qt 5.10 commercial version. I have a QML item which hosts an image. I am trying to pan the QML item when user's finger drags on it OR mouse is dragged.

Following is somewhat I am trying to make my QML item pannable:

Code:

MyQmlItem {
    id: my_qml_item
    anchors.top: parent.top
    anchors.horizontalCenter: parent.horizontalCenter

    onXChanged: {
        if (my_qml_item_mouse_area.drag.active) {
            console.log("x = " + x)
            my_qml_item.x = // what to set x here to move my_qml_item wrt finger or mouse pressed movement
        }
    }
    onYChanged: {
        if (my_qml_item_mouse_area.drag.active) {
            console.log("y = " + y)
            my_qml_item.y = // what to set y here to move my_qml_item wrt finger or mouse pressed movement
        }
    }

    MouseArea {
        id: my_qml_item_mouse_area
        anchors.fill: parent

        drag {
            id: drag_area
            target: my_qml_item
            axis: Drag.XandYAxis
        }

    }
}

I understand that I have to update the x and y position of MyQmlItem when onXChanged and onYChanged is active and x y are getting updated. But I am struggling to figure how I should re-calculate the new my_qml_item.x and my_qml_item.y

Question:
I am getting x and y updates on onXChanged and onYChanged as well. The basic question is, how to calculate plus continuously update my_qml_item.x and my_qml_item.y.

Are there any good examples of Qt/QML for panning or dragging a QML item?

Is there some way to replicate the following anchors by only setting default x and y? Because, it falls in direct conflict with dragging the QML component

anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter

Solution

  • Anchors should not be used if you wish to drag as it links some part of the geometry of the items.

    In your case, you only need to establish the specific positions at certain times, such as when the application starts, so instead of setting the anchors you could use the properties "x", "y", "width" and "height" .

    import QtQuick 2.9
    import QtQuick.Window 2.2
    import QtQuick.Controls 2.2
    
    ApplicationWindow {
        id: app
        visible: true
        visibility: "FullScreen"
        title: qsTr("Scroll")
    
        function resetPosition(){
            item.x = Screen.orientation === Qt.PortraitOrientation ? (Screen.width - item.width)/2 : (Screen.height - item.height)/2
            item.y = 0
        }
    
        Image {
            id: item
            source: "http://doc.qt.io/qt-5/images/declarative-qtlogo.png"
            onStatusChanged:  {
                if(status == Image.Ready)
                    resetPosition()
            }
            MouseArea{
                anchors.fill: parent
                drag.target: item
                drag.axis: Drag.XAndYAxis
                onClicked: resetPosition()
            }
    
        }
    
        property bool isPortrait: Screen.primaryOrientation === Qt.PortraitOrientation || Screen.primaryOrientation === Qt.InvertedPortraitOrientation
        property bool isLandscape: Screen.primaryOrientation === Qt.LandscapeOrientation || Screen.primaryOrientation === Qt.InvertedLandscapeOrientation
    
        onIsPortraitChanged: resetPosition()
        onIsLandscapeChanged: resetPosition()
    }