如何使用QML Scale Element进行不同来源的增量缩放

时间:2014-06-29 17:47:20

标签: qt qml qt-quick

我正在尝试使用QML Scale Element来围绕用户点击的点执行视图缩放,但它并不总是按照文档记录。

要重现此问题,请运行下面的最小QML示例(我在Ubuntu 14.04 x86_64上使用Qt 5.3.1)然后:

  • 点击左上方蓝色矩形的中心。
  • 看到所有内容都按比例放大,但蓝色矩形的中心仍保留在您的点击位置。这与http://doc.qt.io/qt-5/qml-qtquick-scale.html中记录的一样 - “[原点]保持项目缩放的点(即,当项目的其余部分增长时,相对于父项保持固定的点)。” LI>
  • 现在点击红色矩形的中心。
  • 看到所有内容都按比例放大,但红色矩形的中心保留在您的点击位置,它被向上翻译并向左移动。这不是记录在案的。

我的目标是让始终正确缩放,将点击点保持为原点,如文档中所述。

P.S。有趣的是,如果您现在再次单击红色矩形的中心,它会按照承诺在该点附近放大。现在再次单击蓝色矩形的中心,您会看到相同的意外翻译行为。

P.P.S。我正在开发一个应用程序,用户可以在包含矩形的任何地方鼠标滚轮/捏住,内部的所有内容都应该在鼠标/捏合位置周围向上或向下缩放。许多应用程序都有这种行为。参见例如inkscape。

import QtQuick 2.2
import QtQuick.Controls 1.1

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

    Rectangle {
        x: 100
        y: 100
        width: 300
        height: 300

        transform: Scale {
            id: tform
        }

        MouseArea {
            anchors.fill: parent
            onClicked: {
                console.log(mouse.x + " " + mouse.y)
                tform.xScale += 0.5
                tform.yScale += 0.5
                tform.origin.x = mouse.x
                tform.origin.y = mouse.y
            }
        }

        Rectangle {
            x: 50
            y: 50
            width: 50
            height: 50
            color: "blue"
        }

        Rectangle {
            x: 100
            y: 100
            width: 50
            height: 50
            color: "red"
        }

    }

}

(我将此归档为Qt错误,因为该行为不符合文档。在撰写本文时,该错误似乎已被分类为“重要”。https://bugreports.qt.io/browse/QTBUG-40005 - 我仍然非常对这里的解决方案/解决方案的建议非常开放)

1 个答案:

答案 0 :(得分:6)

事实上它是一种偏离行为,只是与阅读文档后的预期不同。

更改矩形的“缩放”变换时,变换将应用于原始矩形。您点击的点从原始矩形的角度保持在同一位置。 这就是为什么当你点击一个角落然后是对角时你的矩形“移动”那么多。

为了达到你想要的效果,你不能依赖变换原点。您必须设置矩形的实际x y坐标。

这是一个有效的例子:

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

    Rectangle {
        id: rect
        x: 100
        y: 100
        width: 300
        height: 300

        Rectangle {
                x: 50
                y: 50
                width: 50
                height: 50
                color: "blue"
            }

            Rectangle {
                x: 100
                y: 100
                width: 50
                height: 50
                color: "red"
            }


        transform: Scale {
            id: tform
        }

        MouseArea {
            anchors.fill: parent
            property double factor: 2.0
            onWheel:
            {
                if(wheel.angleDelta.y > 0)  // zoom in
                    var zoomFactor = factor
                else                        // zoom out
                    zoomFactor = 1/factor   

                var realX = wheel.x * tform.xScale
                var realY = wheel.y * tform.yScale
                rect.x += (1-zoomFactor)*realX
                rect.y += (1-zoomFactor)*realY
                tform.xScale *=zoomFactor
                tform.yScale *=zoomFactor

            }
        }
    }
}