You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何缩放QML矩形而不缩放其子文本?

问题:缩放父容器时如何避免子文本被缩放?

我编写了一个QML组件,通过PinchArea缩放image_boundary矩形是预期行为,但作为其子项的Text也被缩放了,这不符合需求。我已经给Text显式设置了scale: 1.0和固定的font.pointSize,但文本还是会跟着缩放,想知道原因,以及如何实现“属于可缩放组件但自身不缩放的文本”。

原QML代码

import QtQuick 2

Rectangle {
    id: page
    width: 1000; height: 1000
    color: "black"

    Rectangle {
        id: image_boundary
        color: "green"
        width: 200
        height: 100
        x: (parent.width/2)-(image_boundary.width/2)
        y: (parent.height/2)-(image_boundary.height/2)

        onScaleChanged: {
            console.log("Scale changed:", scale)
        }

        PinchArea {
            anchors.fill: image_boundary
            property real initialScale: 1.0
            property real scale: 1.0
            id: pinch_area

            onPinchStarted: {
                initialScale = scale
            }

            onPinchUpdated: function(pinch) {
                scale = initialScale * pinch.scale
                console.log(scale)
                parent.scale = scale
            }
        }
        Text {
            text: "mumble mumble"
            font.pointSize: 10
            scale: 1.0
            color: "yellow"
            anchors.left: parent.right
        }
    }
}

运行用Python代码(基于PySide6)

import sys
from pathlib import Path
from PySide6.QtQuick import QQuickView
from PySide6.QtCore import QUrl
from PySide6.QtGui import QGuiApplication


if __name__ == '__main__':

    #Set up the application window
    app = QGuiApplication(sys.argv)
    view = QQuickView()
    view.setResizeMode(QQuickView.SizeRootObjectToView)

    #Load the QML file
    qml_file = Path(__file__).parent / "test_qml_file.qml"
    view.setSource(QUrl.fromLocalFile(qml_file.resolve()))

    #Show the window
    if view.status() == QQuickView.Error:
        sys.exit(-1)
    view.show()

    #execute and cleanup
    app.exec()
    del view

为什么Text会被缩放?

QML中父项的scale变换是全局继承的,父容器的缩放会直接作用于所有子元素的坐标系。你给Text设置的scale:1.0,是在父容器已经缩放后的空间里保持1倍比例,最终视觉上还是跟着父容器放大/缩小了——相当于父项先把整个坐标系缩放,子项的scale是基于这个缩放后的坐标系计算的,所以无法抵消父项的缩放效果。

解决方法

方案1:将Text移到父容器同级,绑定锚点位置

把Text从image_boundary的子项改成和它同级,直接锚定到目标位置,这样Text完全不受父容器缩放影响:

import QtQuick 2

Rectangle {
    id: page
    width: 1000; height: 1000
    color: "black"

    Rectangle {
        id: image_boundary
        color: "green"
        width: 200
        height: 100
        x: (parent.width/2)-(image_boundary.width/2)
        y: (parent.height/2)-(image_boundary.height/2)

        onScaleChanged: {
            console.log("Scale changed:", scale)
        }

        PinchArea {
            anchors.fill: image_boundary
            property real initialScale: 1.0
            property real scale: 1.0
            id: pinch_area

            onPinchStarted: {
                initialScale = scale
            }

            onPinchUpdated: function(pinch) {
                scale = initialScale * pinch.scale
                console.log(scale)
                parent.scale = scale
            }
        }
    }
    // 移到同级层级,锚定到image_boundary的右侧
    Text {
        text: "mumble mumble"
        font.pointSize: 10
        color: "yellow"
        anchors.left: image_boundary.right
        anchors.verticalCenter: image_boundary.verticalCenter
    }
}

方案2:用中间Item分离缩放层和文本层

如果需要Text保留在原容器层级内,可以在外层套一个Item,只让内部的矩形参与缩放,Text放在外层Item中:

import QtQuick 2

Rectangle {
    id: page
    width: 1000; height: 1000
    color: "black"

    Item {
        id: container
        width: 200
        height: 100
        x: (parent.width/2)-(container.width/2)
        y: (parent.height/2)-(container.height/2)

        // 仅这个矩形参与缩放
        Rectangle {
            id: image_boundary
            color: "green"
            anchors.fill: parent

            onScaleChanged: {
                console.log("Scale changed:", scale)
            }

            PinchArea {
                anchors.fill: image_boundary
                property real initialScale: 1.0
                property real scale: 1.0
                id: pinch_area

                onPinchStarted: {
                    initialScale = scale
                }

                onPinchUpdated: function(pinch) {
                    scale = initialScale * pinch.scale
                    console.log(scale)
                    parent.scale = scale
                }
            }
        }
        // Text放在外层Item,不受缩放影响
        Text {
            text: "mumble mumble"
            font.pointSize: 10
            color: "yellow"
            anchors.left: parent.right
            anchors.verticalCenter: parent.verticalCenter
        }
    }
}

内容的提问来源于stack exchange,提问作者Henry Gomersall

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 09:41:00