C++ 为属性更改触发QML动画

C++ 为属性更改触发QML动画,c++,qt,qml,C++,Qt,Qml,我正在用一些CPU密集型代码实现一个应用程序。此代码必须更新QML中设计的接口以显示其结果 该接口由一个网格和几个块组成,其中包含一些内容。网格完全是C++实现的,块只是QML。< /P> Block.qml import QtQuick 2.3 Item { id: root // lot of non-related stuff here. Behavior on x { NumberAnimation { duratio

我正在用一些CPU密集型代码实现一个应用程序。此代码必须更新QML中设计的接口以显示其结果

该接口由一个网格和几个块组成,其中包含一些内容。<代码>网格完全是C++实现的,块只是QML。< /P>
Block.qml

import QtQuick 2.3

Item {
    id: root

    // lot of non-related stuff here.

    Behavior on x {
        NumberAnimation {
            duration: 1000
            easing.type: Easing.Linear

            onRunningChanged: {
                console.log("behavior on x");
            }
        }
    }

    Behavior on y {
        NumberAnimation {
            duration: 1000
            easing.type: Easing.Linear

            onRunningChanged: {
                console.log("behavior on y");
            }
        }
    }
}

每个块都是用C++创建的,并相应地定位。

问题是,有时我必须移动块,我想触发动画。为了实现这一点,我加入了
行为
元素,您可能已经注意到了这一点

<>但是,当我从C++代码中改变块的位置时,不会触发行为。
只是更改其位置,没有任何动画

我用来更改块位置的代码是:

void Grid::setBlockPosition(QQuickItem *block, unsigned i, unsigned j)
{
    float x, y;
    x = GRID_MARGIN_LEFT + j * this->_blockSize;
    y = GRID_MARGIN_TOP + (GRID_ROWS - i - 1) * this->_blockSize;
    block->setPosition(QPointF(x, y));
}
我也尝试过改变
x
,然后改变
y
,而不是同时改变两者,但结果是一样的


<如何>代码> > x<代码>和<代码> y>代码>属性,从C++ +

这是个好问题。我查看了
QQuickItem
的源代码,它们都有非常相似的代码路径,都发出
geometryChanged()
。你可能认为这就足够了,但事实证明:

应始终使用QObject::setProperty()、QQmlProperty或QMetaProperty::write()更改QML属性值,以确保QML引擎了解属性更改。例如,假设您有一个自定义类型buttonText属性,该属性在内部反映m_buttonText成员变量的值。直接修改成员变量[…]不是一个好主意[…]

由于该值是直接更改的,因此它绕过了Qt的元对象系统,并且QML引擎不知道该属性的更改。这意味着不会更新buttonText的属性绑定,也不会调用任何onButtonTextChanged处理程序

使用特定于代码的示例:例如,如果在QML中更改块的x属性,元对象系统会意识到该更改,并且
行为会收到通知,并以增量直接设置属性,直到它达到目标。当您自己直接设置属性时,
行为
不知道有任何更改,因此它什么也不做

因此,您应该调用
setProperty(“x”,x)
setProperty(“y”,y)

#包括
#包括
#包括
类网格:公共QQuickItem
{
Q_对象
公众:
网格(QQuickItem*父项){
setParentItem(父项);
}
公众时段:
void addBlocks(){
QQmlComponent*blockComponent=新的QQmlComponent(qmlEngine(parentItem()),“Block.qml”);
对于(int i=0;i<4;++i){
QQuickItem*block=qobject_cast(blockComponent->create());
Q_ASSERT(!blockComponent->isError());
块->设置父项(此项);
块->设置属性(“x”,i*100);
块->设置属性(“y”,i*100);
mBlocks.append(块);
}
}
私人:
QList-mBlocks;
};
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
qqmlaplicationengine;
engine.load(QUrl(QStringLiteral(“qrc:/main.qml”));
QQuickItem*contentItem=engine.rootObjects().first()->property(“contentItem”).value();
网格*网格=新网格(contentItem);
网格->添加块();
返回a.exec();
}
#包括“main.moc”

我有关于
QQuickItem
文档详细描述的信息;如果遇到这个问题,希望其他人也能看到这一点。

哇!非常感谢。今晚我将切换到
setProperty
(这是一个宠物项目),测试并回来接受您的答案!
#include <QApplication>
#include <QtQuick>
#include <QtQml>

class Grid : public QQuickItem
{
    Q_OBJECT
public:
    Grid(QQuickItem *parent) {
        setParentItem(parent);
    }

public slots:
    void addBlocks() {
        QQmlComponent *blockComponent = new QQmlComponent(qmlEngine(parentItem()), "Block.qml");
        for (int i = 0; i < 4; ++i) {
            QQuickItem *block = qobject_cast<QQuickItem*>(blockComponent->create());
            Q_ASSERT(!blockComponent->isError());
            block->setParentItem(this);
            block->setProperty("x", i * 100);
            block->setProperty("y", i * 100);
            mBlocks.append(block);
        }
    }

private:
    QList<QQuickItem*> mBlocks;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    QQuickItem *contentItem = engine.rootObjects().first()->property("contentItem").value<QQuickItem*>();
    Grid *grid = new Grid(contentItem);
    grid->addBlocks();

    return a.exec();
}

#include "main.moc"