QML 如何为 属性 的每个变化设置动画? (只有最后一次更改动画可见)
QML how to animate every change of a property? (only the last change animation is visible)
我必须制作一个由 C++ 控制的机械计数器。我是从一张包含数字 (0,1,2,3,4,5,6,7,8,9,0) 的图像中完成的。一次只能看到一个数字。我希望这个计数器只在一个方向(向上)上变化,我想出了这个理论:如果新数字小于旧数字,我首先转到最后一个零,然后禁用动画,转到第一个零,启用动画,最后转到想要的号码。但这行不通。
它立即移动到第一个零,然后随着动画移动到想要的数字。这是代码:
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
id: mainWindow
visible: true
visibility: "Maximized"
property int digit0Y: 0
property bool anim0Enabled: true
Item {
id: root
visible: true
anchors.fill: parent
Rectangle {
id: container
width: 940; height:172
anchors.centerIn: parent
clip: true
color: "black"
NumberElement {
id: digit0
y: mainWindow.digit0Y; x: 0
animationEnabled: anim0Enabled
}
}
}
}
NumberElement.qml:
import QtQuick 2.0
Rectangle {
id: root
property bool animationEnabled: true
width: 130; height: 1892
color: "transparent"
Behavior on y {
enabled: root.animationEnabled
SmoothedAnimation { velocity: 200; duration: 1500; alwaysRunToEnd: true }
}
Image {
id: digits
source: "http://s30.postimg.org/6mmsfxdb5/cifre_global.png"
}
}
编辑:
#include <QQmlComponent>
#include <QGuiApplication>
#include <QThread>
#include <QQmlApplicationEngine>
#include <QQmlProperty>
#include <QDebug>
int number = 0;
int oldDigit = 0;
void set(QObject *object, int number) {
int newDigit = number%10;
if (newDigit < oldDigit) {
QQmlProperty::write(object, "digit0Y", -1720);
QQmlProperty::write(object, "anim0Enabled", false);
QQmlProperty::write(object, "digit0Y", 0);
QQmlProperty::write(object, "anim0Enabled", true);
}
QQmlProperty::write(object, "digit0Y",newDigit*(-172));
oldDigit = newDigit;
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlEngine engine;
QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/main.qml")));
if (component.status() == QQmlComponent::Error) {
qWarning() << component.errorString();
return 1;
}
QObject *object = component.create();
set(object, 9);
//QThread::msleep(1000);
set(object, 1);
return app.exec();
}
通常一个单独的 class 负责设置与某些事件相关的数字,但我试图简化以演示我的问题。在上面的示例中,数字变为 1,并且不关心 set(object, 9)
。那是我的问题。
您需要等待第一个动画完成才能开始第二个动画。您可能会想,“但我将 alwaysRunToEnd
设置为 true
...”,但这对此处没有帮助:
This property holds whether the animation should run to completion when it is stopped.
If this true the animation will complete its current iteration when it is stopped - either by setting the running property to false, or by calling the stop() method.
当前发生的事情是您将 9
设置为数字,这告诉动画它应该开始动画,但是您给出的下一个指令是将 1
设置为数字,它告诉动画停止它正在做的事情并为这个新变化设置动画。
一般来说,通过 QML 处理 Qt Quick 动画更容易。
对于这个特定的用例,我还建议 PathView
,因为它可能更容易实现您所追求的目标。
我必须制作一个由 C++ 控制的机械计数器。我是从一张包含数字 (0,1,2,3,4,5,6,7,8,9,0) 的图像中完成的。一次只能看到一个数字。我希望这个计数器只在一个方向(向上)上变化,我想出了这个理论:如果新数字小于旧数字,我首先转到最后一个零,然后禁用动画,转到第一个零,启用动画,最后转到想要的号码。但这行不通。 它立即移动到第一个零,然后随着动画移动到想要的数字。这是代码:
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
id: mainWindow
visible: true
visibility: "Maximized"
property int digit0Y: 0
property bool anim0Enabled: true
Item {
id: root
visible: true
anchors.fill: parent
Rectangle {
id: container
width: 940; height:172
anchors.centerIn: parent
clip: true
color: "black"
NumberElement {
id: digit0
y: mainWindow.digit0Y; x: 0
animationEnabled: anim0Enabled
}
}
}
}
NumberElement.qml:
import QtQuick 2.0
Rectangle {
id: root
property bool animationEnabled: true
width: 130; height: 1892
color: "transparent"
Behavior on y {
enabled: root.animationEnabled
SmoothedAnimation { velocity: 200; duration: 1500; alwaysRunToEnd: true }
}
Image {
id: digits
source: "http://s30.postimg.org/6mmsfxdb5/cifre_global.png"
}
}
编辑:
#include <QQmlComponent>
#include <QGuiApplication>
#include <QThread>
#include <QQmlApplicationEngine>
#include <QQmlProperty>
#include <QDebug>
int number = 0;
int oldDigit = 0;
void set(QObject *object, int number) {
int newDigit = number%10;
if (newDigit < oldDigit) {
QQmlProperty::write(object, "digit0Y", -1720);
QQmlProperty::write(object, "anim0Enabled", false);
QQmlProperty::write(object, "digit0Y", 0);
QQmlProperty::write(object, "anim0Enabled", true);
}
QQmlProperty::write(object, "digit0Y",newDigit*(-172));
oldDigit = newDigit;
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlEngine engine;
QQmlComponent component(&engine, QUrl(QStringLiteral("qrc:/main.qml")));
if (component.status() == QQmlComponent::Error) {
qWarning() << component.errorString();
return 1;
}
QObject *object = component.create();
set(object, 9);
//QThread::msleep(1000);
set(object, 1);
return app.exec();
}
通常一个单独的 class 负责设置与某些事件相关的数字,但我试图简化以演示我的问题。在上面的示例中,数字变为 1,并且不关心 set(object, 9)
。那是我的问题。
您需要等待第一个动画完成才能开始第二个动画。您可能会想,“但我将 alwaysRunToEnd
设置为 true
...”,但这对此处没有帮助:
This property holds whether the animation should run to completion when it is stopped.
If this true the animation will complete its current iteration when it is stopped - either by setting the running property to false, or by calling the stop() method.
当前发生的事情是您将 9
设置为数字,这告诉动画它应该开始动画,但是您给出的下一个指令是将 1
设置为数字,它告诉动画停止它正在做的事情并为这个新变化设置动画。
一般来说,通过 QML 处理 Qt Quick 动画更容易。
对于这个特定的用例,我还建议 PathView
,因为它可能更容易实现您所追求的目标。