首页 文章

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

提问于
浏览
5

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

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

  • 单击左上方蓝色矩形的中心 .

  • 看到所有内容都按比例放大,但蓝色矩形的中心仍保留在您的点击位置 . 这是http://doc.qt.io/qt-5/qml-qtquick-scale.html中记录的 - "[The origin] holds the point that the item is scaled from (that is, the point that stays fixed relative to the parent as the rest of the item grows)."

  • 现在单击红色矩形的中心 .

  • 看到所有内容都按比例放大,但红色矩形的中心确实保持在您的点击位置,它被向左和向左平移 . 这不是记录在案的 .

我的目标是让它正确地保持点击点作为原点,如文档中所述 .

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

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错误提交,因为行为不遵循文档 . 在编写本文时,错误似乎已经被分类为"important" . https://bugreports.qt.io/browse/QTBUG-40005 - 我仍然非常乐于接受解决方案的建议/解决了这里)

1 回答

  • 5

    事实上,这是一种不正常的行为,只是与阅读文档后的预期不同 .

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

    为了实现你想要的,你不能依赖变换起源 . 您必须设置矩形的实际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
    
                }
            }
        }
    }
    

相关问题