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

QML Unable to change position of item while being dragged by MouseArea

本文关键字:项目 位置 在被 Mousearea 拖动 QML      更新时间:2023-10-16

上下文

我正在尝试使用QML创建瓷砖地图而无需使用QTLocation。我正在尝试设计应用程序,以便只加载必需的瓷砖。这是我提出的策略。

每个瓷砖为256x256 px。瓷砖放在带有嵌套的中继器的网格类中。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控制。看来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> 100,则确实设置了x = 0。但是,这是因为盒子的实际值仍然为100 。如果您在不发布的情况下再次向左移动盒子(x&lt; 100(,您会发现该框以其实际X值返回。抱歉,如果听起来令人困惑,那么自己就更容易理解。

我正在寻找的是加载瓷砖或修复Mousearea问题的替代方法,以便我可以在物品被Mousearea拖动时实际上更改其位置。

另外,我是否有可能实现不同版本的Mousearea,以便我可以在较低的抽象中处理这个问题?

update

我已经能够在一定程度上实现我想要的效果。它似乎工作正常,但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://i.stack.imgur.com/e5qqh.jpg

更新的代码的问题是用rect.x绑定initialX,因此,如果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"
        }
    }
}