How to access a QML's attached property from C++
-
wrote on 4 Sept 2016, 00:09 last edited by MrKozmon 9 Apr 2016, 00:24
E.g. my simple qml is that:
// main.qml import QtQuick 2.0 import QtQuick.Layouts 1.3 RowLayout { width: 100 height: 100 Rectangle { objectName: "myRect" color:"red" Layout.fillWidth: true Layout.fillHeight: true Layout.maximumWidth: 55 } }
Normally I can easily access to a normal property of my qml item (e.g. "color") like that:
// main.cpp QQuickView view; view.setSource(QUrl(QStringLiteral("qrc:/main.qml"))); view.show(); QQuickItem* rootItem = view.rootObject(); QQuickItem* rectangle = rootItem->findChild<QQuickItem*>("myRect"); qDebug() << rectangle->property("color"); // Worked!
But the same thing is not working on attached properties (e.g. "Layout.maximumWidth") like that:
// main.cpp QQuickView view; view.setSource(QUrl(QStringLiteral("qrc:/main.qml"))); view.show(); QQuickItem* rootItem = view.rootObject(); QQuickItem* rectangle = rootItem->findChild<QQuickItem*>("myRect"); qDebug() << rectangle->property("Layout.maximumWidth"); // Not worked!
Plus, I've tired
QQmlContext
's contextProperty() function, andQQmlProperty
's read() function withQQmlProperty(QObject *obj, const QString &name, QQmlContext *ctxt)
as referred here and these are not working also, e.g:// main.cpp QQuickView view; view.setSource(QUrl(QStringLiteral("qrc:/main.qml"))); view.show(); QQuickItem* rootItem = view.rootObject(); QQuickItem* rectangle = rootItem->findChild<QQuickItem*>("myRect"); QQmlProperty property(rectangle, "Layout.maximumWidth",view.rootContext()); qDebug() << property.read(); // Not worked!
The console output I got everytime:
QML debugging is enabled. Only use this in a safe environment. QVariant(Invalid)
On the other hand I've found an another way to access attached properties (source):
template<typename T> QObject *qmlAttachedPropertiesObject(const QObject *attachee, bool create = true)
But this function only work with user defined
typename T
s like that example code. Because I've no access to the type of LayoutQQuickLayoutAttached
, it's private (source).In short, even Qt documentation says (source):
As QML uses Qt's meta-type system all of the existing QMetaObject classes can be used to introspect and interact with objects created by QML. However, some of the new features provided by QML - such as type safety and attached properties - are most easily used through the QQmlProperty class that simplifies some of their natural complexity.
And says (source):
Creating a QQmlProperty without a context will render some properties - like attached properties - inaccessible.
So according to documentations I should be able to read attached properties from C++ already, but I can't.
-
wrote on 4 Sept 2016, 16:33 last edited by
I've found a way to do it, but It's not actually efficient. Please share if you know better. Thanks.
QQuickView view; view.setSource(QStringLiteral("qrc:/main.qml")); view.show(); QQuickItem* item = view.rootObject()->findChild<QQuickItem*>("myRect"); for(auto obj : item->children()) if (0 == QString::compare(obj->metaObject()->className(), "QQuickLayoutAttached")) { qDebug() << obj->property("maximumWidth"); break; }
-
wrote on 5 Sept 2016, 22:32 last edited by
QQmlProperty works with a small adjustment. Instead of the root context, use the context for the object.
QQmlProperty property(rectangle, "Layout.maximumWidth", qmlContext(rectangle));
-
wrote on 6 Sept 2016, 15:43 last edited by
Wow! Worked, thank you!
I did not know that every single child objects have its own QQmlContext, I thought that all the qml childs are evaluated in rootContext.
1/4