QML在被MouseArea拖动时无法更改项目的位置

时间:2018-04-23 06:37:28

标签: c++ qt qml

上下文

我正在尝试使用QML创建平铺地图而不使用QtLocation。我正在尝试设计应用程序,以便只加载基本的磁贴。这是我提出的策略。

每个图块为256x256像素。切片放置在具有嵌套Repeater的Grid类中。 xOffset确定应加载到网格中的切片。

        Grid{
            id: mapgrid
            rows: 6
            columns: 9
            spacing: 1
            Repeater{
                model: 6
                Repeater{
                    model: 9
                    property int outerIndex: index
                    Tile{
                        imgsrc: "image://provider/" + maprect.zoomLevel + '/' + (index + maprect.xOffset) + '/' + (outerIndex+maprect.yOffset)
                    }
                }
            }
        }

当网格向左移动256个像素时,应加载一组新的切片。这可以通过更改偏移值来实现。然后我可以再次将网格移动256个像素,使其在视图中返回。

        onXChanged: {
            if(x <= -512){
                maprect.x = -256;
                maprect.xOffset++;
            }
        }

问题

我的网格的移动由MouseArea控制,其中drag.target设置为它。似乎MouseArea控制坐标直到释放鼠标。这是一个简单的例子:

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Text{
        z:1
        text: "X: " + rect.x
    }

    MouseArea{
        id:marea
        anchors.fill: rect
        drag.target: rect

    }

    Rectangle{
        id: rect
        height: 256
        width: 256
        color: "red"
        onXChanged: {
            if(x > 100){
                x = 0;
            }
        }
    }
}

如果您将框移到x> gt; 100,确实设置了x = 0。然而,这是因为盒子的实际价值仍然是100+。如果再次向左移动框(x <100)而不释放,您将发现该框返回其实际x值。对不起,如果听起来令人困惑,那么自己更容易理解。

我正在寻找的是另一种加载磁贴或修复MouseArea问题的方法,这样我实际上可以在被MouseArea拖动时更改项目的位置。

另外,我可以实现不同版本的MouseArea,这样我就能以较低的抽象来处理这个问题吗?

更新

我已经能够在一定程度上达到我想要的效果。它看起来工作正常,但QML正在检测绑定循环。

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    id: wind
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Rectangle{
        id: wrapper
        height: wind.height
        width: wind.width
        MouseArea{
            id:marea
            anchors.fill: wrapper
            //drag.target: rect

            property int initialX: 0

            property int iniMouseX;
            onEntered: {
                initialX = rect.x
                iniMouseX = mouseX
                console.log ("set")
            }
        }

        Rectangle{
            id: rect
            height: 256
            width: 256
            border.color: "green"
            x: marea.initialX + (marea.mouseX - marea.iniMouseX)
            color: "red"

            onXChanged: {
                if(rect.x > 200){
                    marea.initialX -= 200;
                }
            }

        }
    }
}

https://imgur.com/a/zmu5eiO

1 个答案:

答案 0 :(得分:0)

更新代码的问题是initialXrect.x绑定,因此如果rect.x更新,则会调用onXChanged,如果rect.x > 200将更新再次initialX,这将成为无限循环。 所以解决这个问题就是解决方案,让事件像流程一样:

Window {
    id: wind
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Rectangle{
        id: wrapper
        height: wind.height
        width: wind.width
        MouseArea{
            id:marea
            anchors.fill: wrapper
            //drag.target: rect

            property int initialX: 0

            property int iniMouseX;
            onEntered: {
                initialX = rect.x
                iniMouseX = mouseX
                console.log ("set")
            }
            onMouseXChanged: {
                if(rect.x > 200){
                    marea.initialX -= 200;
                }
                rect.x = marea.initialX + (marea.mouseX - marea.iniMouseX)
            }
        }

        Rectangle{
            id: rect
            height: 256
            width: 256
            border.color: "green"
            color: "red"
        }
    }
}