我正在使用一些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
属性的行为?
答案 0 :(得分:5)
这是一个很好的问题。我查看了QQuickItem
的来源,setX(),setY()和setPosition()都有非常相似的代码路径,所有代码路径都发出geometryChanged()
。您可能认为这就足够了,但事实证明it's not:
您应该始终使用QObject :: setProperty(),QQmlProperty或QMetaProperty :: write()来更改QML属性值,以确保QML引擎知道属性更改。例如,假设您有一个带有buttonText属性的自定义类型PushButton,该属性在内部反映了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"
我added this了解QQuickItem
文档详细说明的信息;希望其他人看到这个,如果他们遇到这个问题。