C++ 为属性更改触发QML动画
我正在用一些CPU密集型代码实现一个应用程序。此代码必须更新QML中设计的接口以显示其结果 该接口由一个网格和几个块组成,其中包含一些内容。<代码>网格完全是C++实现的,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
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"