Qml - Как остановить перетаскивание прямоугольника за пределы его родителя - PullRequest
0 голосов
/ 05 мая 2020

Я использую qml для создания прямоугольника изменяемого размера, который можно перетащить внутрь его родительской панели, но нельзя перетащить наружу (рис. 1). Когда я изменяю его размер, например, с помощью верхнего левого маркера, он отлично работает и не может быть изменен вне его родительского элемента (рис. 2). Но когда я перетаскиваю весь прямоугольник, его можно вытащить за пределы своего родителя (рис. 3). Мой код пытается использовать один и тот же logi c для обоих, т.е. когда левая сторона прямоугольника достигает левой стороны его родителя, перетаскивание отменяется. Прекрасно работает для изменения размера, но не при перетаскивании прямоугольника. Что я делаю не так?

Fig 1 Fig 2 Fig3

Pane {
            id: compPane
            implicitHeight: imageListModel.reqViewHeight
            implicitWidth: imageListModel.reqViewWidth
            leftPadding: 0
            topPadding: 0
            clip: true

            background: Rectangle{
                id: backgroundRect
                anchors.fill: parent
                color: "gray"
                border.color: "black"
                border.width: 6
            }

            // Resizable rectangle that can be dragged
            Rectangle {
                id: indRect
                x:parent.width / 4
                y: parent.height / 4
                width: parent.width / 2
                height: parent.width / 2
                border {
                    width: 2
                    color: "steelblue"
                }
                color: "#354682B4"

                MouseArea {
                    id: indImagesDragArea
                    anchors.fill: parent
                    anchors.margins: 8
                    drag.target: parent

                    onPositionChanged: {
                        if (drag.active){
                            if (indRect.x <= 0 + backgroundRect.border.width)
                                Drag.cancel()
                            if (indRect.x + indRect.width >= (compPane.width - backgroundRect.border.width) )
                                Drag.cancel()
                        }
                    }
                }

                // Top Left handle - works well
                Rectangle {
                    width: 15
                    height: 15
                    color: "steelblue"
                    anchors.verticalCenter:parent.top
                    anchors.horizontalCenter: parent.left
                    MouseArea {
                        anchors.fill: parent
                        cursorShape: Qt.SizeFDiagCursor
                        drag{ target: parent; axis: Drag.XAndYAxis }
                        onPositionChanged: {
                            if(drag.active){
                                //var delta = Math.max(mouseX, mouseY)
                                var newWidth = indRect.width - mouseX
                                var newHeight = indRect.height - mouseY;

                                if (newWidth < width || newHeight < height)
                                    return

                                if (indRect.x <= 0 + backgroundRect.border.width && mouseX < 0){
                                    Drag.cancel()
                                    indRect.x =  0 + backgroundRect.border.width
                                }
                                else {
                                    indRect.width = newWidth
                                    indRect.x = indRect.x + mouseX
                                }

                                if (indRect.y <= 0 + backgroundRect.border.width && mouseY < 0){
                                    Drag.cancel()
                                    indRect.y = 0 + backgroundRect.border.width
                                }
                                else{
                                    indRect.height = newHeight
                                    indRect.y = indRect.y + mouseY
                                }
                            }
                        }
                    }
                }
            }
        }

Ответы [ 2 ]

1 голос
/ 05 мая 2020

Drag.cancel() фактически предназначен для использования при реализации типов взаимодействия перетаскивания. В этом случае его вызовы ничего не делают, потому что вы никогда не запускаете одну из этих последовательностей. Ваш пример левого верхнего маркера работает нормально, если вы закомментируете вызовы Drag.cancel().

Почему ваш левый верхний пример работает, потому что вы ограничиваете x и y при обновлениях позиции, чтобы закрепить их на сцене через явные обновления indRect.x и indRect.y. Вам просто нужно реализовать ту же технику для основного сценария перетаскивания.

Например:

onPositionChanged: {
    if (drag.active){
        if (indRect.x <= 0 + backgroundRect.border.width)
            indRect.x =  0 + backgroundRect.border.width;
        if (indRect.x + indRect.width >= (compPane.width - backgroundRect.border.width) )
            indRect.x = compPane.width - backgroundRect.border.width - indRect.width;
    }
}
0 голосов
/ 05 мая 2020

Вы можете попробовать использовать свойство drag.minimum и drag.maximum. См. Документацию:

https://doc.qt.io/qt-5/qml-qtquick-mousearea.html#drag .threshold-prop

...