如何在 NumberAnimation 中正确地将值绑定到 'from' 和 'to'?

How to properly bind values to 'from' and 'to', inside a NumberAnimation?

我想做一个水平滚动的文字动画(右边进入,穿过屏幕,左边退出,重复)。

import QtQuick 2.4
import QtQuick.Window 2.2
Window {
    id: root
    visible: true
    Rectangle {
        id: scrollLine
        anchors.fill: parent
        color: "black"
        Text {
            id: scrollText
            color: "white"
            text: "This is a test"
            font.pixelSize: parent.height * 0.5
            anchors.verticalCenter: parent.verticalCenter
            x: scrollLine.width
            NumberAnimation on x {
                id: scrollAnimation
                from: scrollLine.width; to: -scrollText.width
                duration: 5000
                loops: Animation.Infinite
                running: true
            }
        }
    }
}

问题是,我的文字很奇怪。出现在左侧,向左滚动两个字符,重复...绑定有问题 from: scrollLine.width; to: -scrollText.width, 但我不知道是什么。

您的代码稍作修改即可按预期工作。我没有使用 font.pixelSize: parent.height*0.5,而是使用了固定大小的点。试试这个

import QtQuick 2.4
import QtQuick.Window 2.2
Window {
    id: root
    visible: true
    Rectangle {
        id: scrollLine
        anchors.fill: parent
        color: "black"
        Text {
            id: scrollText
            color: "white"
            text: "This is a test"
            font.pixelSize: 150; //////// Changed this
            anchors.verticalCenter: parent.verticalCenter
            x: scrollLine.width
            NumberAnimation on x {
                id: scrollAnimation
                from: scrollText.width; to: -scrollText.width
                duration: 5000
                loops: Animation.Infinite
                running: true
            }
        }
    }
}

啊,这很奇怪! :)

我首先看到的是这个

x: scrollLine.width

什么都不做。 NumberAnimation 立即运行,导致设置 Textx 值,因此我们可以删除该代码以便更容易找到问题。

接下来要做的是打印出项目的 widths:

import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    id: root
    visible: true

    Rectangle {
        id: scrollLine
        anchors.fill: parent
        color: "black"
        onHeightChanged: print("rectangle height", height)

        Text {
            id: scrollText
            color: "white"
            text: "This is a test"
            font.pixelSize: parent.height * 0.5
            anchors.verticalCenter: parent.verticalCenter
            onWidthChanged: print("text width", width)

            NumberAnimation on x {
                id: scrollAnimation
                from: scrollLine.width
                to: -scrollText.width
                duration: 5000
                loops: Animation.Infinite
                running: true
            }
        }
    }
}

这给了我们:

qml: text width 72.078125
qml: rectangle height 160
qml: text width 443.734375

好吧,文本大小改变宽度很奇怪,但是...它间接取决于 window 的大小,对吧?我们将其 font.pixelSize 设置为 parent.height * 0.5。恰好 window 大小是在 Text 获得初始大小后确定的。但是,作为一种声明性语言,您会认为这应该可行。

让我们检查动画的 fromto 值:

onFromChanged: print("from", from)
onToChanged: print("to", to)

现在我们得到:

qml: from 0
qml: to 0
qml: text width 72.078125
qml: to -72.078125
qml: from 160
qml: rectangle height 160
qml: text width 443.734375
qml: to -443.734375

它们最初是不正确的,当然,但它们最终会变得正确。这闻起来像个虫子。让我们通过打印出 Text:

x 位置来仔细检查
qml: x -0.576625
...
qml: x -71.4654609375

这是不对的。这似乎是一个错误。我也以为是,但后来我检查了 documentation:

If the NumberAnimation is defined within a Transition or Behavior, this value defaults to the value defined in the starting state of the Transition, or the current value of the property at the moment the Behavior is triggered.

您没有使用 Behavior,尽管语法看起来非常相似。多一点搜索显示 documentation for the on keyword:

The animation starts as soon as the rectangle is loaded, and will automatically be applied to its x and y values.

所以,这不是错误。您必须以某种方式为动画提供合理的 fromto 值。一种解决方案是对值进行硬编码:

import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    id: root
    width: 250
    height: 250
    visible: true

    Rectangle {
        id: scrollLine
        anchors.fill: parent
        color: "black"

        Text {
            id: scrollText
            color: "white"
            text: "This is a test"
            font.pixelSize: parent.height * 0.5
            anchors.verticalCenter: parent.verticalCenter

            NumberAnimation on x {
                id: scrollAnimation
                from: root.width
                to: -1000
                duration: 5000
                loops: Animation.Infinite
                running: true
            }
        }
    }
}

不过,最好的解决方案可能是不依赖 window 的 height 字体大小。 Qt 选择的默认字体大小在所有提供合理 ​​DPI 信息的平台上都清晰可见,因此最好将其乘以某个系数:

import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    id: root
    width: 250
    height: 250
    visible: true

    Rectangle {
        id: scrollLine
        anchors.fill: parent
        color: "black"

        FontMetrics {
            id: fontMetrics
        }

        Text {
            id: scrollText
            color: "white"
            text: "This is a test"
            font.pixelSize: fontMetrics.font.pixelSize * 8
            anchors.verticalCenter: parent.verticalCenter

            NumberAnimation on x {
                id: scrollAnimation
                from: root.width
                to: -1000
                duration: 5000
                loops: Animation.Infinite
                running: true
            }
        }
    }
}