Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to access a QML's attached property from C++

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

Scheduled Pinned Locked Moved Solved General and Desktop
4 Posts 2 Posters 4.2k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • MrKozmonM Offline
    MrKozmonM Offline
    MrKozmon
    wrote on last edited by MrKozmon
    #1

    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.

    1 Reply Last reply
    0
    • MrKozmonM Offline
      MrKozmonM Offline
      MrKozmon
      wrote on last edited by
      #2

      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; }
      
      1 Reply Last reply
      1
      • jeremy_kJ Offline
        jeremy_kJ Offline
        jeremy_k
        wrote on last edited by
        #3

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

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

        Asking a question about code? http://eel.is/iso-c++/testcase/

        1 Reply Last reply
        2
        • MrKozmonM Offline
          MrKozmonM Offline
          MrKozmon
          wrote on last edited by
          #4

          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 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved