1

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
TheWaterProgrammer
  • 7,055
  • 12
  • 70
  • 159
  • Do you want to move the item when you press and move the mouse? – eyllanesc Feb 04 '18 at 19:18
  • Why do you want to change the Y coordinate when the x changes, and vice versa? – eyllanesc Feb 04 '18 at 19:24
  • oh. thats a mistake. I will edit-correct that – TheWaterProgrammer Feb 04 '18 at 19:33
  • yep. edited corrected. @eyllanesc yes. I want to move the item when you press and move the mouse – TheWaterProgrammer Feb 04 '18 at 19:34
  • even worse, you are creating an infinite loop – eyllanesc Feb 04 '18 at 19:35
  • 1
    Execute this: https://gist.github.com/eyllanesc/2851e202856317ee06c3153ed6e9c23e – eyllanesc Feb 04 '18 at 19:35
  • 1
    you should not change a property in the signal that indicates its change because when you finish changing it you will call again, and that new call will do it again, etc. – eyllanesc Feb 04 '18 at 19:40
  • yep your suggestion works. I was doing a mistake in the code which I missed to mention in the sample code I gave in the question. I have 2 anchors which on `my_qml_item`. `anchors.top: parent.top` and `anchors.horizontalCenter: parent.horizontalCenter`. I need to figure out how to set them only when the position is reset or initially set. – TheWaterProgrammer Feb 04 '18 at 19:41
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/164503/discussion-between-illegalskillsexception-and-eyllanesc). – TheWaterProgrammer Feb 04 '18 at 19:43
  • You should not use the properties if you want to drag the items. Why do not you use X and Y instead of anchors? – eyllanesc Feb 04 '18 at 19:44
  • I need the anchoring to establish the correct default X and Y. I need to store the default X and Y when my item becomes visible first time. yep – TheWaterProgrammer Feb 04 '18 at 19:53
  • @eyllanesc I have an additional question about the anchors. Because they are tightly related to getting the Drag QML component work. It will great if you could consider this in your answer. It will be a good package for anyone trying to learn how to pan a qml item and also get around default anchoring which most of use so widely in Qt apps – TheWaterProgrammer Feb 06 '18 at 18:29
  • I have one last query, the initial position of the item is in the upper central part, if it does not move and the screen is rotated, should the position be higher in relation to the new orientation, or should it change as if it had moved? – eyllanesc Feb 06 '18 at 18:37
  • Try the following code and tell me if something is missing? https://gist.github.com/eyllanesc/1437e07716e4ed229a199f992a79b71d – eyllanesc Feb 06 '18 at 18:39
  • if the orientation changes then it should just reset it back to default position. that is `y = 0`. This should keep it simple? – TheWaterProgrammer Feb 06 '18 at 18:40
  • If the item is moved, and then the orientation of the screen is changed, should the position be reset? – eyllanesc Feb 06 '18 at 18:42
  • I have added another version, try it https://gist.github.com/eyllanesc/1437e07716e4ed229a199f992a79b71d – eyllanesc Feb 06 '18 at 18:50
  • yep. the position should be reset to default to keep it simple. is it something seriously wrong to reset back the position on orientation change? – TheWaterProgrammer Feb 06 '18 at 18:50
  • The second version does what you want, I am knowing your requirements since you are not very clear in describing what you want. – eyllanesc Feb 06 '18 at 18:52
  • @eyllanesc I did not want to get into the orientation change scenario with this question since that is a problem I should solve myself. This is question is only to deal with basic dragging of a QML item. Can you please post an answer based on your second proposal. it works for me. I can accept the answer. yep – TheWaterProgrammer Feb 06 '18 at 18:54
  • I already published my answer. – eyllanesc Feb 06 '18 at 19:01

1 Answers1

3

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()
}
eyllanesc
  • 235,170
  • 19
  • 170
  • 241