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 C++ classes and structs in QML
QtWS25 Last Chance

using C++ classes and structs in QML

Scheduled Pinned Locked Moved Solved QML and Qt Quick
30 Posts 9 Posters 5.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.
  • mzimmersM Offline
    mzimmersM Offline
    mzimmers
    wrote on last edited by mzimmers
    #1

    this will be a progressive question, starting first with the simplest: what am I doing wrong here?

    class MyClass : public QObject {
        Q_OBJECT
        QML_ELEMENT
        int m_classInt = 55;
    public:
        MyClass() {}
        Q_PROPERTY(int classInt MEMBER m_classInt)
    };
    Q_DECLARE_METATYPE(MyClass)
    

    and

    Window {
        width: 640
        height: 480
        visible: true
    
        property MyClass ccc
        ColumnLayout {
            Label { text: ccc.classInt }
        }
    }
    

    returns:

    TypeError: Cannot read property 'classInt' of null
    

    I must be overlooking something insanely obvious, but...what am I missing here?

    Thanks...

    EDIT:

    Renamed title of topic to better reflect the current issue.

    SGaistS 1 Reply Last reply
    0
    • GrecKoG Offline
      GrecKoG Offline
      GrecKo
      Qt Champions 2018
      wrote on last edited by GrecKo
      #19

      You can now instantiate Gadgets from QML with undocumented macros (so maybe don't use it).

      Use QML_VALUE_TYPE(typeName) with a lower case name like you currently do.
      Then you can add QML_CONSTRUCTIBLE_VALUE or QML_STRUCTURED_VALUE (even both).

      QML_CONSTRUCTIBLE_VALUE will call a user defined constructor

      if you have Q_INVOKABLE MyStruct(int foo) : m_myInt{foo} {}
      then doing property myStruct myStruct1: 42 will call the constructor with 42 as the foo param

      QML_STRUCTURED_VALUE will assign properties depending on the js object you passed in QML.

      property myStruct myStruct1: ({myInt: 42}) will create a default constructed MyStruct and assign its myInt property to 42.

      Note that the type should always be default constructible.

      EDIT: Note that you don't have to use QML_ELEMENT, Q_DECLARE_METATYPE or qmlRegisterType if you use Q_GADGET and QML_VALUE_TYPE.

      mzimmersM L 2 Replies Last reply
      3
      • mzimmersM mzimmers

        this will be a progressive question, starting first with the simplest: what am I doing wrong here?

        class MyClass : public QObject {
            Q_OBJECT
            QML_ELEMENT
            int m_classInt = 55;
        public:
            MyClass() {}
            Q_PROPERTY(int classInt MEMBER m_classInt)
        };
        Q_DECLARE_METATYPE(MyClass)
        

        and

        Window {
            width: 640
            height: 480
            visible: true
        
            property MyClass ccc
            ColumnLayout {
                Label { text: ccc.classInt }
            }
        }
        

        returns:

        TypeError: Cannot read property 'classInt' of null
        

        I must be overlooking something insanely obvious, but...what am I missing here?

        Thanks...

        EDIT:

        Renamed title of topic to better reflect the current issue.

        SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Hi,

        You declared a property named ccc of type MyClass but you did not assign a value to it.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        mzimmersM 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          You declared a property named ccc of type MyClass but you did not assign a value to it.

          mzimmersM Offline
          mzimmersM Offline
          mzimmers
          wrote on last edited by
          #3

          @SGaist I thought that declaring the property did instantiate the type (class) of the property -- not so?

          If not, how do I do it? I tried this:

          property MyClass ccc: MyClass
          

          but QML still reports it as null.

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #4

            Based on this documentation, you are missing {} to create the object.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            mzimmersM 1 Reply Last reply
            0
            • SGaistS SGaist

              Based on this documentation, you are missing {} to create the object.

              mzimmersM Offline
              mzimmersM Offline
              mzimmers
              wrote on last edited by mzimmers
              #5

              @SGaist I looked at the doc you referenced, and tried a few things. It appears that there are two ways to instantiate a C++ object in QML:

                  property MyClass myClass1: MyClass {
                      classInt: 44
                  }
                  MyClass {
                      id: myClass2
                      classInt: 33
                  }
              

              I don't know if these are identical "under the hood," but preliminary testing indicates that they both work.

              Moreover, I found that I could access enums in the class with the following:

              class MyClass : public QObject {
                  Q_OBJECT
                  QML_ELEMENT
                  int m_classInt = 55;
              signals:
                  Q_INVOKABLE void classIntChanged();
              public:
                  MyClass() {}
                  Q_PROPERTY(int classInt MEMBER m_classInt NOTIFY classIntChanged)
                  enum MyEnums {
                      Enum0,
                      Enum1,
                      Enum2,
                      Enum3
                  } m_myEnums;
                  Q_ENUM(MyEnums)
              };
              

              (I added the notify stuff to suppress a runtime warning.)
              In the QML:

              Label { text: "MyClass.Enum2: " + MyClass.Enum2 }
              

              What I eventually discovered, and which is rather obscurely documented here, is that the enum names must begin with uppercase or the QML doesn't recognize them.

              The ability to use enums without actually instantiating an object is excellent news, and was actually my 2nd part of the question.

              Now, for the 3rd and hopefully final part: using a struct instead of a class. I'm running into what seem like conflicting requirements here. If I name my struct with a starting uppercase letter, I get a runtime error on this line:

              // main.cpp
                  qmlRegisterType<MyStruct>("MyStruct", 1, 0, "MyStruct");
              

              the error is:

              qt.qml.typeregistration: Invalid QML element name "MyStruct"; value type names should begin with a lowercase letter
              

              But if I rename my struct to "myStruct" and change this line:

                  qmlRegisterType<myStruct>("myStruct", 1, 0, "myStruct");
              

              Then I get a build time error in my qml:

                  property myStruct myStructXXX: myStruct {}
              

              "error: Expected type name"

              It appears that I'm getting something mixed up in the registration, but I can't quite decode what. Any suggestions? Thanks...

              J.HilkJ B 2 Replies Last reply
              0
              • mzimmersM mzimmers

                @SGaist I looked at the doc you referenced, and tried a few things. It appears that there are two ways to instantiate a C++ object in QML:

                    property MyClass myClass1: MyClass {
                        classInt: 44
                    }
                    MyClass {
                        id: myClass2
                        classInt: 33
                    }
                

                I don't know if these are identical "under the hood," but preliminary testing indicates that they both work.

                Moreover, I found that I could access enums in the class with the following:

                class MyClass : public QObject {
                    Q_OBJECT
                    QML_ELEMENT
                    int m_classInt = 55;
                signals:
                    Q_INVOKABLE void classIntChanged();
                public:
                    MyClass() {}
                    Q_PROPERTY(int classInt MEMBER m_classInt NOTIFY classIntChanged)
                    enum MyEnums {
                        Enum0,
                        Enum1,
                        Enum2,
                        Enum3
                    } m_myEnums;
                    Q_ENUM(MyEnums)
                };
                

                (I added the notify stuff to suppress a runtime warning.)
                In the QML:

                Label { text: "MyClass.Enum2: " + MyClass.Enum2 }
                

                What I eventually discovered, and which is rather obscurely documented here, is that the enum names must begin with uppercase or the QML doesn't recognize them.

                The ability to use enums without actually instantiating an object is excellent news, and was actually my 2nd part of the question.

                Now, for the 3rd and hopefully final part: using a struct instead of a class. I'm running into what seem like conflicting requirements here. If I name my struct with a starting uppercase letter, I get a runtime error on this line:

                // main.cpp
                    qmlRegisterType<MyStruct>("MyStruct", 1, 0, "MyStruct");
                

                the error is:

                qt.qml.typeregistration: Invalid QML element name "MyStruct"; value type names should begin with a lowercase letter
                

                But if I rename my struct to "myStruct" and change this line:

                    qmlRegisterType<myStruct>("myStruct", 1, 0, "myStruct");
                

                Then I get a build time error in my qml:

                    property myStruct myStructXXX: myStruct {}
                

                "error: Expected type name"

                It appears that I'm getting something mixed up in the registration, but I can't quite decode what. Any suggestions? Thanks...

                J.HilkJ Offline
                J.HilkJ Offline
                J.Hilk
                Moderators
                wrote on last edited by
                #6

                @mzimmers a struct and a class are literally the same in c++ 😉

                did you forget to add Q_GADGET in your struct ?


                Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                Q: What's that?
                A: It's blue light.
                Q: What does it do?
                A: It turns blue.

                mzimmersM SGaistS 2 Replies Last reply
                1
                • mzimmersM mzimmers

                  @SGaist I looked at the doc you referenced, and tried a few things. It appears that there are two ways to instantiate a C++ object in QML:

                      property MyClass myClass1: MyClass {
                          classInt: 44
                      }
                      MyClass {
                          id: myClass2
                          classInt: 33
                      }
                  

                  I don't know if these are identical "under the hood," but preliminary testing indicates that they both work.

                  Moreover, I found that I could access enums in the class with the following:

                  class MyClass : public QObject {
                      Q_OBJECT
                      QML_ELEMENT
                      int m_classInt = 55;
                  signals:
                      Q_INVOKABLE void classIntChanged();
                  public:
                      MyClass() {}
                      Q_PROPERTY(int classInt MEMBER m_classInt NOTIFY classIntChanged)
                      enum MyEnums {
                          Enum0,
                          Enum1,
                          Enum2,
                          Enum3
                      } m_myEnums;
                      Q_ENUM(MyEnums)
                  };
                  

                  (I added the notify stuff to suppress a runtime warning.)
                  In the QML:

                  Label { text: "MyClass.Enum2: " + MyClass.Enum2 }
                  

                  What I eventually discovered, and which is rather obscurely documented here, is that the enum names must begin with uppercase or the QML doesn't recognize them.

                  The ability to use enums without actually instantiating an object is excellent news, and was actually my 2nd part of the question.

                  Now, for the 3rd and hopefully final part: using a struct instead of a class. I'm running into what seem like conflicting requirements here. If I name my struct with a starting uppercase letter, I get a runtime error on this line:

                  // main.cpp
                      qmlRegisterType<MyStruct>("MyStruct", 1, 0, "MyStruct");
                  

                  the error is:

                  qt.qml.typeregistration: Invalid QML element name "MyStruct"; value type names should begin with a lowercase letter
                  

                  But if I rename my struct to "myStruct" and change this line:

                      qmlRegisterType<myStruct>("myStruct", 1, 0, "myStruct");
                  

                  Then I get a build time error in my qml:

                      property myStruct myStructXXX: myStruct {}
                  

                  "error: Expected type name"

                  It appears that I'm getting something mixed up in the registration, but I can't quite decode what. Any suggestions? Thanks...

                  B Offline
                  B Offline
                  Bob64
                  wrote on last edited by
                  #7

                  @mzimmers said in using C++ class in QML:

                  @SGaist I looked at the doc you referenced, and tried a few things. It appears that there are two ways to instantiate a C++ object in QML:

                      property MyClass myClass1: MyClass {
                          classInt: 44
                      }
                      MyClass {
                          id: myClass2
                          classInt: 33
                      }
                  

                  I don't know if these are identical "under the hood," but preliminary testing indicates that they both work.

                  As I understand it, they are both essentially the same in terms of instantiating the object. The difference is that in the second case the instance is instantiated and added as a child of your containing component (much like any other nested QML component), whereas in the first case you are assigning the instance to a property of your component.

                  1 Reply Last reply
                  0
                  • J.HilkJ J.Hilk

                    @mzimmers a struct and a class are literally the same in c++ 😉

                    did you forget to add Q_GADGET in your struct ?

                    mzimmersM Offline
                    mzimmersM Offline
                    mzimmers
                    wrote on last edited by mzimmers
                    #8

                    @J-Hilk said in using C++ class in QML:

                    did you forget to add Q_GADGET in your struct ?

                    No, but I must be doing something just as silly. I even converted my struct to a class, so now I have:

                    class MyStruct {
                        Q_GADGET
                        QML_ELEMENT
                        Q_PROPERTY(int myInt MEMBER m_myInt)
                        int m_myInt = 55;
                    public:
                        MyStruct() {}
                    };
                    Q_DECLARE_METATYPE(MyStruct)
                    

                    along with:

                    class MyClass : public QObject {
                        Q_OBJECT
                        QML_ELEMENT
                        Q_PROPERTY(int classInt MEMBER m_classInt NOTIFY classIntChanged)
                        int m_classInt = 55;
                    signals:
                        Q_INVOKABLE void classIntChanged();
                    public:
                        MyClass() {}
                    };
                    Q_DECLARE_METATYPE(MyClass)
                    

                    and in main.cpp:

                        qmlRegisterType<MyStruct>("MyStruct", 1, 0, "MyStruct");
                        qmlRegisterType<MyClass>("MyClass", 1, 0, "MyClass");
                    

                    The first line produces a runtime error: "Invalid QML element name "MyStruct"; value type names should begin with a lowercase letter" while the second line works fine.

                    Somewhere, I'm overlooking one of the magic Qt macros, but I sure can't see it.

                    EDIT:

                    It works if I subclass MyStruct from QObject. This is OK for this little example, but has implications for my real project. Somehow I'm not getting Q_GADGET properly set up.

                    1 Reply Last reply
                    0
                    • J.HilkJ J.Hilk

                      @mzimmers a struct and a class are literally the same in c++ 😉

                      did you forget to add Q_GADGET in your struct ?

                      SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #9

                      @J-Hilk said in using C++ classes and structs in QML:

                      @mzimmers a struct and a class are literally the same in c++ 😉

                      Nope, there's key difference: the former has everything public by default while the latter has everything private.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      mzimmersM 1 Reply Last reply
                      0
                      • SGaistS SGaist

                        @J-Hilk said in using C++ classes and structs in QML:

                        @mzimmers a struct and a class are literally the same in c++ 😉

                        Nope, there's key difference: the former has everything public by default while the latter has everything private.

                        mzimmersM Offline
                        mzimmersM Offline
                        mzimmers
                        wrote on last edited by mzimmers
                        #10

                        @SGaist true enough, but I think I've obviated that difference with my use of the "public" keyword:
                        EDIT: I neglected to point out that the Q_GADGET macro causes everything declared after it to be private unless explicitly declared to the contrary, hence my use of public.

                        struct MyStruct {
                            Q_GADGET
                        public:
                            QML_ELEMENT
                            QML_VALUE_TYPE(myStruct)
                            Q_PROPERTY(int myInt MEMBER m_myInt)
                            int m_myInt = 55;
                            MyStruct() {}
                        };
                        Q_DECLARE_METATYPE(MyStruct)
                        

                        With this declaration, I get a build error on this line:

                        property myStruct myStruct1: myStruct {
                        

                        "error: Expected type name"

                        jsulmJ 1 Reply Last reply
                        0
                        • mzimmersM mzimmers

                          @SGaist true enough, but I think I've obviated that difference with my use of the "public" keyword:
                          EDIT: I neglected to point out that the Q_GADGET macro causes everything declared after it to be private unless explicitly declared to the contrary, hence my use of public.

                          struct MyStruct {
                              Q_GADGET
                          public:
                              QML_ELEMENT
                              QML_VALUE_TYPE(myStruct)
                              Q_PROPERTY(int myInt MEMBER m_myInt)
                              int m_myInt = 55;
                              MyStruct() {}
                          };
                          Q_DECLARE_METATYPE(MyStruct)
                          

                          With this declaration, I get a build error on this line:

                          property myStruct myStruct1: myStruct {
                          

                          "error: Expected type name"

                          jsulmJ Offline
                          jsulmJ Offline
                          jsulm
                          Lifetime Qt Champion
                          wrote on last edited by
                          #11

                          @mzimmers Isn't the name of the struct MyStruct and not myStruct?

                          https://forum.qt.io/topic/113070/qt-code-of-conduct

                          mzimmersM 1 Reply Last reply
                          0
                          • jsulmJ jsulm

                            @mzimmers Isn't the name of the struct MyStruct and not myStruct?

                            mzimmersM Offline
                            mzimmersM Offline
                            mzimmers
                            wrote on last edited by
                            #12

                            @jsulm if you're referring to the QML line of code, I get an error if I try to use "MyStruct:"
                            Screenshot 2023-10-09 162726.png

                            J.HilkJ 1 Reply Last reply
                            0
                            • mzimmersM mzimmers

                              @jsulm if you're referring to the QML line of code, I get an error if I try to use "MyStruct:"
                              Screenshot 2023-10-09 162726.png

                              J.HilkJ Offline
                              J.HilkJ Offline
                              J.Hilk
                              Moderators
                              wrote on last edited by
                              #13

                              @mzimmers can you show the full (copy pasted) content of your qml file ?
                              we haven't seen that and maybe its a simple error there

                              @SGaist said in using C++ classes and structs in QML:

                              Nope, there's key difference: the former has everything public by default while the latter has everything private

                              mäh, tomato/tomato, it changes the default but you can still declare private /prublic manually


                              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                              Q: What's that?
                              A: It's blue light.
                              Q: What does it do?
                              A: It turns blue.

                              mzimmersM 1 Reply Last reply
                              0
                              • J.HilkJ J.Hilk

                                @mzimmers can you show the full (copy pasted) content of your qml file ?
                                we haven't seen that and maybe its a simple error there

                                @SGaist said in using C++ classes and structs in QML:

                                Nope, there's key difference: the former has everything public by default while the latter has everything private

                                mäh, tomato/tomato, it changes the default but you can still declare private /prublic manually

                                mzimmersM Offline
                                mzimmersM Offline
                                mzimmers
                                wrote on last edited by
                                #14

                                @J-Hilk sure - I'll post from the top to the point of errors (I'm skipping the Labels that I use for telltales):

                                import QtQuick
                                import QtQuick.Controls
                                import QtQuick.Layouts
                                import QtQuick.Window
                                
                                import MyStruct
                                
                                Window {
                                    id: mainWindow
                                    width: 640
                                    height: 480
                                    visible: true
                                
                                    property MyStruct myStruct1: MyStruct {
                                        myInt: 100
                                    }
                                
                                    MyStruct {
                                        id: myStruct2
                                        myInt: 200
                                    }
                                

                                While I'm at it, here's my main.cpp ("struct" is the project name):

                                #include <QGuiApplication>
                                #include <QQmlContext>
                                #include <QQmlApplicationEngine>
                                
                                #include "mystruct.h"
                                #include "myclass.h"
                                
                                int main(int argc, char *argv[])
                                {
                                    QGuiApplication app(argc, argv);
                                    QQmlApplicationEngine engine;
                                
                                    qmlRegisterType<MyStruct>("MyStruct", 1, 0, "MyStruct"); // tried "myStruct" too
                                    qmlRegisterType<MyClass>("MyClass", 1, 0, "MyClass");
                                
                                    QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
                                        &app, []() { QCoreApplication::exit(-1); },
                                        Qt::QueuedConnection);
                                
                                    engine.loadFromModule("struct", "Main");
                                
                                    return app.exec();
                                }
                                
                                J.HilkJ 1 Reply Last reply
                                0
                                • mzimmersM mzimmers

                                  @J-Hilk sure - I'll post from the top to the point of errors (I'm skipping the Labels that I use for telltales):

                                  import QtQuick
                                  import QtQuick.Controls
                                  import QtQuick.Layouts
                                  import QtQuick.Window
                                  
                                  import MyStruct
                                  
                                  Window {
                                      id: mainWindow
                                      width: 640
                                      height: 480
                                      visible: true
                                  
                                      property MyStruct myStruct1: MyStruct {
                                          myInt: 100
                                      }
                                  
                                      MyStruct {
                                          id: myStruct2
                                          myInt: 200
                                      }
                                  

                                  While I'm at it, here's my main.cpp ("struct" is the project name):

                                  #include <QGuiApplication>
                                  #include <QQmlContext>
                                  #include <QQmlApplicationEngine>
                                  
                                  #include "mystruct.h"
                                  #include "myclass.h"
                                  
                                  int main(int argc, char *argv[])
                                  {
                                      QGuiApplication app(argc, argv);
                                      QQmlApplicationEngine engine;
                                  
                                      qmlRegisterType<MyStruct>("MyStruct", 1, 0, "MyStruct"); // tried "myStruct" too
                                      qmlRegisterType<MyClass>("MyClass", 1, 0, "MyClass");
                                  
                                      QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
                                          &app, []() { QCoreApplication::exit(-1); },
                                          Qt::QueuedConnection);
                                  
                                      engine.loadFromModule("struct", "Main");
                                  
                                      return app.exec();
                                  }
                                  
                                  J.HilkJ Offline
                                  J.HilkJ Offline
                                  J.Hilk
                                  Moderators
                                  wrote on last edited by
                                  #15

                                  don't know if that changed with Qt6 but shouldn't this

                                  @mzimmers said in using C++ classes and structs in QML:

                                  import MyStruct

                                  be

                                  import MyStruct 1.0

                                  ?


                                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                                  Q: What's that?
                                  A: It's blue light.
                                  Q: What does it do?
                                  A: It turns blue.

                                  mzimmersM 1 Reply Last reply
                                  0
                                  • J.HilkJ J.Hilk

                                    don't know if that changed with Qt6 but shouldn't this

                                    @mzimmers said in using C++ classes and structs in QML:

                                    import MyStruct

                                    be

                                    import MyStruct 1.0

                                    ?

                                    mzimmersM Offline
                                    mzimmersM Offline
                                    mzimmers
                                    wrote on last edited by mzimmers
                                    #16

                                    @J-Hilk that doesn't seem to matter any more. If you try to import a version number that's higher than what you registered, you'll get a runtime error, but that's about it.

                                    This is just nuts, though. In main.cpp, this line:

                                    qmlRegisterType<MyStruct>("myStruct", 1, 0, "myStruct");
                                    

                                    Produces a warning from the editor/code model/whatever that QML types must begin with uppercase. Plus it won't build, giving an error at my QML declaration "error: Expected type name".

                                    But if I modify that line in main.cpp to:

                                    qmlRegisterType<MyStruct>("myStruct", 1, 0, "MyStruct"); // tried "myStruct" too
                                    

                                    and then I have to change my Main.qml to:

                                        property MyStruct myStruct1: MyStruct {
                                    

                                    I get a runtime error: "qt.qml.typeregistration: Invalid QML element name "MyStruct"; value type names should begin with a lowercase letter"

                                    It's almost as though I shouldn't be registering my struct, though I don't know what the alternative might be.

                                    L 1 Reply Last reply
                                    1
                                    • mzimmersM mzimmers

                                      @J-Hilk that doesn't seem to matter any more. If you try to import a version number that's higher than what you registered, you'll get a runtime error, but that's about it.

                                      This is just nuts, though. In main.cpp, this line:

                                      qmlRegisterType<MyStruct>("myStruct", 1, 0, "myStruct");
                                      

                                      Produces a warning from the editor/code model/whatever that QML types must begin with uppercase. Plus it won't build, giving an error at my QML declaration "error: Expected type name".

                                      But if I modify that line in main.cpp to:

                                      qmlRegisterType<MyStruct>("myStruct", 1, 0, "MyStruct"); // tried "myStruct" too
                                      

                                      and then I have to change my Main.qml to:

                                          property MyStruct myStruct1: MyStruct {
                                      

                                      I get a runtime error: "qt.qml.typeregistration: Invalid QML element name "MyStruct"; value type names should begin with a lowercase letter"

                                      It's almost as though I shouldn't be registering my struct, though I don't know what the alternative might be.

                                      L Offline
                                      L Offline
                                      lemons
                                      wrote on last edited by
                                      #17

                                      @mzimmers
                                      I thought the Q_GADGET macro is used for meta-types only, which can't be instantiated from QML.
                                      To be used e.g. if the struct is a property of an QObject derived class, which is somehow accessible in QML (either passed through C++ or created in QML).
                                      Allows you to use e.g. Q_PROPERTY macros, without the QObject overhead.

                                      To be creatable from QML you need a derived class from QObject, so the Q_GADGET macro is not sufficient, as it is missing e.g. the signals and slots of the QObject class.

                                      Note: I can be totally wrong / outdated, but this is how I was thinking and using it all the time :D

                                      JoeCFDJ 1 Reply Last reply
                                      1
                                      • L lemons

                                        @mzimmers
                                        I thought the Q_GADGET macro is used for meta-types only, which can't be instantiated from QML.
                                        To be used e.g. if the struct is a property of an QObject derived class, which is somehow accessible in QML (either passed through C++ or created in QML).
                                        Allows you to use e.g. Q_PROPERTY macros, without the QObject overhead.

                                        To be creatable from QML you need a derived class from QObject, so the Q_GADGET macro is not sufficient, as it is missing e.g. the signals and slots of the QObject class.

                                        Note: I can be totally wrong / outdated, but this is how I was thinking and using it all the time :D

                                        JoeCFDJ Offline
                                        JoeCFDJ Offline
                                        JoeCFD
                                        wrote on last edited by JoeCFD
                                        #18

                                        @lemons said in using C++ classes and structs in QML:

                                        Q_GADGET macro

                                        Lemons seems right.

                                        In QML (Qt Meta-Object Language), the Q_GADGET macro is typically used with C++ classes to create non-instantiable classes that can be registered with the Qt meta-object system. These classes are similar to Q_OBJECT classes but cannot have signals, slots, or properties. They are often used for data-only structures that need to be exposed to QML.

                                        I use upper case for my class registration in qmlRegisterType without issues. I guess lower case is needed in app_engine->rootContext()->setContextProperty( ... );

                                        1 Reply Last reply
                                        0
                                        • GrecKoG Offline
                                          GrecKoG Offline
                                          GrecKo
                                          Qt Champions 2018
                                          wrote on last edited by GrecKo
                                          #19

                                          You can now instantiate Gadgets from QML with undocumented macros (so maybe don't use it).

                                          Use QML_VALUE_TYPE(typeName) with a lower case name like you currently do.
                                          Then you can add QML_CONSTRUCTIBLE_VALUE or QML_STRUCTURED_VALUE (even both).

                                          QML_CONSTRUCTIBLE_VALUE will call a user defined constructor

                                          if you have Q_INVOKABLE MyStruct(int foo) : m_myInt{foo} {}
                                          then doing property myStruct myStruct1: 42 will call the constructor with 42 as the foo param

                                          QML_STRUCTURED_VALUE will assign properties depending on the js object you passed in QML.

                                          property myStruct myStruct1: ({myInt: 42}) will create a default constructed MyStruct and assign its myInt property to 42.

                                          Note that the type should always be default constructible.

                                          EDIT: Note that you don't have to use QML_ELEMENT, Q_DECLARE_METATYPE or qmlRegisterType if you use Q_GADGET and QML_VALUE_TYPE.

                                          mzimmersM L 2 Replies Last reply
                                          3
                                          • GrecKoG GrecKo

                                            You can now instantiate Gadgets from QML with undocumented macros (so maybe don't use it).

                                            Use QML_VALUE_TYPE(typeName) with a lower case name like you currently do.
                                            Then you can add QML_CONSTRUCTIBLE_VALUE or QML_STRUCTURED_VALUE (even both).

                                            QML_CONSTRUCTIBLE_VALUE will call a user defined constructor

                                            if you have Q_INVOKABLE MyStruct(int foo) : m_myInt{foo} {}
                                            then doing property myStruct myStruct1: 42 will call the constructor with 42 as the foo param

                                            QML_STRUCTURED_VALUE will assign properties depending on the js object you passed in QML.

                                            property myStruct myStruct1: ({myInt: 42}) will create a default constructed MyStruct and assign its myInt property to 42.

                                            Note that the type should always be default constructible.

                                            EDIT: Note that you don't have to use QML_ELEMENT, Q_DECLARE_METATYPE or qmlRegisterType if you use Q_GADGET and QML_VALUE_TYPE.

                                            mzimmersM Offline
                                            mzimmersM Offline
                                            mzimmers
                                            wrote on last edited by
                                            #20

                                            @GrecKo curiouser and curiouser.

                                            My modified struct:

                                            struct MyStruct {
                                                QML_STRUCTURED_VALUE
                                                QML_VALUE_TYPE(myStruct)
                                                Q_PROPERTY(int myInt MEMBER m_myInt)
                                                int m_myInt = 55;
                                                MyStruct() {}
                                            };
                                            

                                            my registration (in main.cpp):

                                                qmlRegisterType<MyStruct>("myStruct", 1, 0, "MyStruct");
                                            

                                            and my QML:

                                            property myStruct myStruct1: myStruct ({myInt: 100})
                                            

                                            produces a runtime error: "myStruct is not a type."

                                            Isn't using QML_VALUE_TYPE intended to allow me to use "myStruct" in the QML?

                                            GrecKoG 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