触发特性更改的QML动画
Triggering QML animation for property changes
我正在用一些CPU密集型代码实现一个应用程序。此代码必须更新QML中设计的接口以显示其结果。
该界面由一个网格和几个块组成,其中包含一些内容。Grid
是完全C++实现的,而Block
只是QML。
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++中创建的,并相应地进行定位。
问题是,有时我必须移动块,我想触发一个动画。为了实现这一点,我包含了Behavior
元素,您可能已经注意到了。
但是,当我从C++代码更改块的位置时,行为不会被触发。Block
只是简单地更改其位置,而没有任何动画。
我用来更改块位置的代码是:
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
,而不是同时更改两者,但结果相同。
如何从C++触发x
和y
属性上的行为?
这是个好问题。我研究了QQuickItem
的源代码,setX()、setY()和setPosition()都有非常相似的代码路径,它们都发出geometryChanged()
。你可能会认为这就足够了,但事实证明这还不够:
您应该始终使用QObject::setProperty()、QQmlProperty或QMetaProperty::write()来更改QML属性值,以确保QML引擎了解属性更改。例如,假设您有一个自定义类型PushButton,其buttonText属性在内部反映m_buttonText成员变量的值。直接修改成员变量[…]不是一个好主意[…]。
由于该值是直接更改的,因此这会绕过Qt的元对象系统,并且QML引擎不会意识到属性更改。这意味着到buttonText的属性绑定将不会更新,也不会调用任何onButtonTextChanged处理程序。
使用特定于代码的示例:例如,如果您在QML中更改块的x属性,则元对象系统会意识到这一更改,Behavior
会收到通知,并以增量直接设置该属性,直到它达到目标。当您自己直接设置属性时,Behavior
不知道有任何更改,因此它什么也不做。
因此,您应该调用setProperty("x", x)
和setProperty("y", y)
:
#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"
我已经将这些信息添加到QQuickItem
文档的详细描述中;如果遇到这个问题,希望其他人也能看到。
- 在执行其他功能的同时播放动画(LED矩阵和Arduino/ESP8266)
- 从C++实例化QML
- 使用CMake创建QML插件
- QT通过C++添加映射QML项目
- 如何在没有信号的情况下从C++执行QML插槽
- QML按钮点击功能执行顺序
- QML:修改在不同QML文件(而非main.QML)中定义的子对象的属性
- 建议在运行时将带有类实例的列表从c++导入qml
- Qt Quick-如何仅从c++代码与qml属性交互
- 如何将带有自定义对象的容器从C++传递到QML
- 使用 GLUT 使用键停止动画?
- QML 使用带有参数C++函数
- QML:设置动画图像源,而不加载资源中的文件
- 如何在C++中的值更改时触发动画 qml
- 单击按钮后对QML矩形的颜色设置动画
- Qml在无帧QQuickView(QtQuick2)中的动画上闪烁
- 触发特性更改的QML动画
- QML如何对属性的每次更改进行动画处理?(只有最后一个更改动画可见)
- QML动画完成后调用c++函数
- 如何从C++启动 QML 动画