How to access a QML's attached property from C++



  • 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, and QQmlProperty's read() function with QQmlProperty(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 Ts like that example code. Because I've no access to the type of Layout QQuickLayoutAttached, 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.



  • 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; }
    


  • QQmlProperty works with a small adjustment. Instead of the root context, use the context for the object.

    QQmlProperty property(rectangle, "Layout.maximumWidth", qmlContext(rectangle));



  • 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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.