Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Using non-creatable type in QML
Forum Updated to NodeBB v4.3 + New Features

Using non-creatable type in QML

Scheduled Pinned Locked Moved QML and Qt Quick
8 Posts 4 Posters 9.9k Views 1 Watching
  • 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.
  • R Offline
    R Offline
    Roland_R
    wrote on last edited by
    #1

    I played with QML/C++ interfacing this week. In a test projet I wanted to declare a QML property using a type that is registered via qmlRegisterUncreatableType(). The property is initialized with 'null' in QML. To my surprise I get the error message "Element is not creatable." on application start although there is no attempt to create in instance of this class in QML. Does someone have an idea what I'm doing wrong?

    1 Reply Last reply
    0
    • C Offline
      C Offline
      chrisadams
      wrote on last edited by
      #2

      You cannot declare properties of an uncreatable type in an object declaration in QML. You can declare properties of an uncreatable type in a C++ type declaration only.

      For example, the following works:
      @
      class MyQmlType : public QObject
      {
      Q_OBJECT
      Q_PROPERTY(MyUncreatableType *someProp READ accessor CONSTANT)

      public:
      MyQmlType();
      ~MyQmlType();
      MyUncreatableType *someProp() const;
      }
      @

      But the following does not:
      @
      Item {
      property MyUncreatableType someProp
      }
      @

      In practice, this does make uncreatable types somewhat less useful from QML, I agree.

      Cheers,
      Chris.

      1 Reply Last reply
      0
      • R Offline
        R Offline
        Roland_R
        wrote on last edited by
        #3

        Maybe I was not explicit enough. What i did was: declare a type in C++ and register it with qmlRegisterUncreatableType() for QML interop. Then I used it in QML like this
        @
        Item {
        property MyUncreatableType someProp = null
        }
        @

        I intended to set the property in a QML function later on. But I immediatly received the error mentioned above when I started the app. If you were right, then the only use for uncreatable types would be for declaring globals via QmlContext::setContextProperty.

        My expectation was this uncreatable registration would simply prevent creating objects in QML - not using them in QML. Maybe it's a bug?

        1 Reply Last reply
        0
        • C Offline
          C Offline
          chrisadams
          wrote on last edited by
          #4

          I understood you. As I said, you cannot declare a property whose type is uncreatable in a QML object declaration.

          No, you're not correct is stating that the only use for uncreatable types is for declaring globals via context properties. They are also useful as properties of C++-defined types, as I explained in my original response.

          Your expectation is basically correct, but due to the way that property declaration occurs in a QML object instance, this also means that you cannot declare properties of such uncreatable types in QML. It's not a bug. It's expected (although I agree suboptimal) behaviour.

          Cheers,
          Chris.

          1 Reply Last reply
          0
          • R Offline
            R Offline
            Roland_R
            wrote on last edited by
            #5

            Thank you for the details.

            But if the observed behavior is expected then the current documentation is obviously incomplete as it seems to match my expectations.

            bq.
            This template function registers the C++ type in the QML system with the name qmlName, in the library imported from uri having the version number composed from versionMajor and versionMinor.
            While the type has a name and a type, it cannot be created, and the given error message will result if creation is attempted.
            This is useful where the type is only intended for providing attached properties or enum values.

            1 Reply Last reply
            0
            • C Offline
              C Offline
              chrisadams
              wrote on last edited by
              #6

              Hi,

              You're right - it should be expanded to explicitly mention that properties of that type cannot be declared. Please file a bug report about this issue.

              Thanks,
              Chris.

              1 Reply Last reply
              0
              • R Offline
                R Offline
                Richard15
                wrote on last edited by Richard15
                #7

                So this is still a bug (documentation or otherwise) two years later.

                After reading the Qt 5.4 documentation, I fully expected to be able to use a type registered in this way, and this thread is the only comment I've found anywhere that say you can't.

                Quote from the Qt 5.4 docs:

                This is useful if a type's enums or attached properties should be accessible from QML but the type itself should not be instantiable.

                It is in fact strictly necessary to do this in many cases, as it is common for QObjects to be impossible to create without additional parameters.

                I just want a place to put a pointer to my QObject. Is that really impossible?

                QML still has incredibly poor documentation throughout. There are a huge number of circular links, and a lot of "magic" functions that appear to exist yet are totally undocumented - pretty much everything to do with Models, for example.

                M 1 Reply Last reply
                0
                • R Richard15

                  So this is still a bug (documentation or otherwise) two years later.

                  After reading the Qt 5.4 documentation, I fully expected to be able to use a type registered in this way, and this thread is the only comment I've found anywhere that say you can't.

                  Quote from the Qt 5.4 docs:

                  This is useful if a type's enums or attached properties should be accessible from QML but the type itself should not be instantiable.

                  It is in fact strictly necessary to do this in many cases, as it is common for QObjects to be impossible to create without additional parameters.

                  I just want a place to put a pointer to my QObject. Is that really impossible?

                  QML still has incredibly poor documentation throughout. There are a huge number of circular links, and a lot of "magic" functions that appear to exist yet are totally undocumented - pretty much everything to do with Models, for example.

                  M Offline
                  M Offline
                  MFry
                  wrote on last edited by MFry
                  #8

                  @Richard15,

                  I'm pretty new to Qt and QML but as I'm currently researching this topic myself, I thought I'd let you know what I've found. You can gain access to instances of uncreatable types via the setContextProperty call.

                  C++

                  QQuickView view;
                  qmlRegisterUncreatableType<MyType>("myUri", 1, 0, "Don't try to add to a qml definition");
                  view->rootContext()->setContextProperty("myInstance", myInstance);
                  

                  QML

                  import myUri 1.0
                  Item {
                    property int something: myInstance.something // binding a C++ property to QML
                    property int somethingElse: 0
                    function doSomething () {
                      myInstance.doSomething(); // calling a Q_INVOKABLE
                    }
                    Connections {
                      target: myInstance
                      onSomethingChanged: { // property changed signal handler
                      }
                  }
                  

                  as referenced here: http://doc.qt.io/qt-5/qtqml-cppintegration-contextproperties.html#setting-an-object-as-a-context-property .

                  Another way you can pass uncreatable types to QML is through a Q_INVOKABLE method called from a creatable type or another context property. The downsides are that the Connections don't work despite everything else seemingly functioning properly. You have to use connect in the Javascript. Also, because these are loaded dynamically you need to verify their existence first which is kind of hacky. Assuming you have the above class defined and is accessible from QML using setContextProperty:

                  C++

                  qmlRegisterUncreatableType<MyOtherType>("myUri", 1, 0, "Don't try to add to a qml definition");
                  

                  QML

                  import myUri 1.0
                  Item {
                    property var myOtherInstance
                    property int myProperty: myOtherInstance !== null ? myOtherInstance.something : 0 // property depending on existence of the instance
                    Component.onCompleted: {
                      myOtherInstance = myInstance.getOtherInstance();
                    }
                    onMyOtherInstanceChanged: {
                      myOtherInstance.doSomething() // Q_INVOKABLE
                      myOtherInstance.onSomethingChanged.connect( function () { console.debug("something changed!") } ); // signal handler for Q_PROPERTY
                    }
                  

                  edit: There is another major component to this. By passing the Q_OBJECT to the QML, it takes ownership of that object and will garbage collect it. For objects intended to contain persistent data, as you might imagine, this is not ideal. You will need to give explicit ownership to the C++.

                  QQmlEngine::setObjectOwnership(myInstance, QQMLEngine::CppOwnership);

                  info here: https://wiki.qt.io/SharedPointersAndQmlOwnership

                  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