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. Creating a C++ defined object in QML
Forum Updated to NodeBB v4.3 + New Features

Creating a C++ defined object in QML

Scheduled Pinned Locked Moved Solved QML and Qt Quick
7 Posts 3 Posters 1.0k 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.
  • M Offline
    M Offline
    mzimmers
    wrote on 21 Feb 2024, 16:08 last edited by mzimmers
    #1

    Hi all -

    This is similar to, but different from, an earlier thread.

    I have a QML file that accepts an argument. The argument is a C++ defined object, and may be null, depending on the use case. If it's not null, I want to make a local copy (which seems to be working). If it is null, I want to create a new instance of this object (which isn't working).

    Here's the class:

    class Schedule : public QObject
    {
        Q_OBJECT
        QML_ELEMENT
    public:
        Q_INVOKABLE explicit Schedule(QObject *parent = nullptr);
        Q_INVOKABLE static Schedule *cloneSchedule(Schedule *source);
    

    And the QML file:

    ColumnLayout {
        property Schedule schedule // sometimes null depending on caller
        property Schedule scheduleCopy
        property Schedule newSchedule: Schedule
    
        Component.onCompleted: {
            if (schedule !== null) {
                console.log("ScheduleCreateEdit.qml: creating clone of Schedule in list.")
                scheduleCopy = schedule.cloneSchedule(schedule)
            } else {
                console.log("ScheduleCreateEdit.qml: creating new Schedule.")
                // nothing I've tried here works; it's always null.
                scheduleCopy = new Schedule//newSchedule//schedule.cloneSchedule(newSchedule)
            }
        }
    

    How do I correctly code the creation of a new instance of this class?

    Thanks...

    G 1 Reply Last reply 21 Feb 2024, 16:37
    0
    • M mzimmers
      21 Feb 2024, 18:51

      @Bob64 I tried this, and it seems to work:

      ColumnLayout {
          id: scheduleCreate
          property Schedule schedule
          property Schedule scheduleCopy
          Schedule {
              id: newSchedule
          }
      
          Component.onCompleted: {
              if (schedule !== null) {
                  scheduleCopy = schedule.cloneSchedule(schedule)
              } else {
                  scheduleCopy = newSchedule.cloneSchedule(newSchedule)
              }
      

      If I understand your suggestion, it would be more like this:

      Component {
          id: scheduleComponent
          Schedule {
              id: newSchedule
          }
      }
      property Schedule scheduleCopy
      
      Component.onCompleted: {
          if (schedule !== null) {
              scheduleCopy = schedule.cloneSchedule(schedule)
          } else {
              scheduleCopy = scheduleComponent.createObject(*** what goes in here? ***)
      

      Right? So, what are the arguments to createObject() in this case?

      Thanks...

      B Offline
      B Offline
      Bob64
      wrote on 21 Feb 2024, 21:46 last edited by Bob64
      #6

      @mzimmers I think it's the parent as the first argument and then an optional JS object argument of any properties you want to initialise it with.

      Something like:

          scheduleComponent.createObject(scheduleCreate, {"prop1": prop1Val, "prop2": prop2Val, ...})
      

      I don't know if that's the correct parent for your case and of course you might not want to set any initial properties, in which case leave out the second argument. (Edit: looking more closely at your example, you don't seem to set any properties, but I guess you might have simplified it compared with the real thing.)

      M 1 Reply Last reply 21 Feb 2024, 22:03
      1
      • M mzimmers
        21 Feb 2024, 16:08

        Hi all -

        This is similar to, but different from, an earlier thread.

        I have a QML file that accepts an argument. The argument is a C++ defined object, and may be null, depending on the use case. If it's not null, I want to make a local copy (which seems to be working). If it is null, I want to create a new instance of this object (which isn't working).

        Here's the class:

        class Schedule : public QObject
        {
            Q_OBJECT
            QML_ELEMENT
        public:
            Q_INVOKABLE explicit Schedule(QObject *parent = nullptr);
            Q_INVOKABLE static Schedule *cloneSchedule(Schedule *source);
        

        And the QML file:

        ColumnLayout {
            property Schedule schedule // sometimes null depending on caller
            property Schedule scheduleCopy
            property Schedule newSchedule: Schedule
        
            Component.onCompleted: {
                if (schedule !== null) {
                    console.log("ScheduleCreateEdit.qml: creating clone of Schedule in list.")
                    scheduleCopy = schedule.cloneSchedule(schedule)
                } else {
                    console.log("ScheduleCreateEdit.qml: creating new Schedule.")
                    // nothing I've tried here works; it's always null.
                    scheduleCopy = new Schedule//newSchedule//schedule.cloneSchedule(newSchedule)
                }
            }
        

        How do I correctly code the creation of a new instance of this class?

        Thanks...

        G Offline
        G Offline
        GrecKo
        Qt Champions 2018
        wrote on 21 Feb 2024, 16:37 last edited by
        #2

        @mzimmers said in Creating a C++ defined object in QML:

        If it is null, I want to create a new instance of this object (which isn't working).

        What will be the use of this new instance?

        M 1 Reply Last reply 21 Feb 2024, 16:59
        0
        • G GrecKo
          21 Feb 2024, 16:37

          @mzimmers said in Creating a C++ defined object in QML:

          If it is null, I want to create a new instance of this object (which isn't working).

          What will be the use of this new instance?

          M Offline
          M Offline
          mzimmers
          wrote on 21 Feb 2024, 16:59 last edited by mzimmers
          #3

          @GrecKo said in Creating a C++ defined object in QML:

          What will be the use of this new instance?

          To serve as a template for the user to populate, and then send a command to add the new instance to the model list. It's perfectly fine if this is a temporary copy; it only exists for the user to edit.

          EDIT:

          It seems like all I need to do is invoke the class c'tor, but I can't figure out the correct syntax to do this in QML.

          B 1 Reply Last reply 21 Feb 2024, 18:36
          0
          • M mzimmers
            21 Feb 2024, 16:59

            @GrecKo said in Creating a C++ defined object in QML:

            What will be the use of this new instance?

            To serve as a template for the user to populate, and then send a command to add the new instance to the model list. It's perfectly fine if this is a temporary copy; it only exists for the user to edit.

            EDIT:

            It seems like all I need to do is invoke the class c'tor, but I can't figure out the correct syntax to do this in QML.

            B Offline
            B Offline
            Bob64
            wrote on 21 Feb 2024, 18:36 last edited by
            #4

            @mzimmers in the simplest case you would construct a C++ object exposed to QML simply by using it as a QML object:

            ColumnLayout {
                MyCppObject { ...}
            }
            

            You want to create it dynamically though so can you do something like wrapping it in a Component and then using createObject to instantiate it?

            Component {
                id: myCppObjectComponent
                MyCppObject {}
            }
            
            ...
            
                var myCppObj =  myCppObjectComponent.createObject(...)
            
            M 1 Reply Last reply 21 Feb 2024, 18:51
            1
            • B Bob64
              21 Feb 2024, 18:36

              @mzimmers in the simplest case you would construct a C++ object exposed to QML simply by using it as a QML object:

              ColumnLayout {
                  MyCppObject { ...}
              }
              

              You want to create it dynamically though so can you do something like wrapping it in a Component and then using createObject to instantiate it?

              Component {
                  id: myCppObjectComponent
                  MyCppObject {}
              }
              
              ...
              
                  var myCppObj =  myCppObjectComponent.createObject(...)
              
              M Offline
              M Offline
              mzimmers
              wrote on 21 Feb 2024, 18:51 last edited by
              #5

              @Bob64 I tried this, and it seems to work:

              ColumnLayout {
                  id: scheduleCreate
                  property Schedule schedule
                  property Schedule scheduleCopy
                  Schedule {
                      id: newSchedule
                  }
              
                  Component.onCompleted: {
                      if (schedule !== null) {
                          scheduleCopy = schedule.cloneSchedule(schedule)
                      } else {
                          scheduleCopy = newSchedule.cloneSchedule(newSchedule)
                      }
              

              If I understand your suggestion, it would be more like this:

              Component {
                  id: scheduleComponent
                  Schedule {
                      id: newSchedule
                  }
              }
              property Schedule scheduleCopy
              
              Component.onCompleted: {
                  if (schedule !== null) {
                      scheduleCopy = schedule.cloneSchedule(schedule)
                  } else {
                      scheduleCopy = scheduleComponent.createObject(*** what goes in here? ***)
              

              Right? So, what are the arguments to createObject() in this case?

              Thanks...

              B 1 Reply Last reply 21 Feb 2024, 21:46
              0
              • M mzimmers
                21 Feb 2024, 18:51

                @Bob64 I tried this, and it seems to work:

                ColumnLayout {
                    id: scheduleCreate
                    property Schedule schedule
                    property Schedule scheduleCopy
                    Schedule {
                        id: newSchedule
                    }
                
                    Component.onCompleted: {
                        if (schedule !== null) {
                            scheduleCopy = schedule.cloneSchedule(schedule)
                        } else {
                            scheduleCopy = newSchedule.cloneSchedule(newSchedule)
                        }
                

                If I understand your suggestion, it would be more like this:

                Component {
                    id: scheduleComponent
                    Schedule {
                        id: newSchedule
                    }
                }
                property Schedule scheduleCopy
                
                Component.onCompleted: {
                    if (schedule !== null) {
                        scheduleCopy = schedule.cloneSchedule(schedule)
                    } else {
                        scheduleCopy = scheduleComponent.createObject(*** what goes in here? ***)
                

                Right? So, what are the arguments to createObject() in this case?

                Thanks...

                B Offline
                B Offline
                Bob64
                wrote on 21 Feb 2024, 21:46 last edited by Bob64
                #6

                @mzimmers I think it's the parent as the first argument and then an optional JS object argument of any properties you want to initialise it with.

                Something like:

                    scheduleComponent.createObject(scheduleCreate, {"prop1": prop1Val, "prop2": prop2Val, ...})
                

                I don't know if that's the correct parent for your case and of course you might not want to set any initial properties, in which case leave out the second argument. (Edit: looking more closely at your example, you don't seem to set any properties, but I guess you might have simplified it compared with the real thing.)

                M 1 Reply Last reply 21 Feb 2024, 22:03
                1
                • B Bob64
                  21 Feb 2024, 21:46

                  @mzimmers I think it's the parent as the first argument and then an optional JS object argument of any properties you want to initialise it with.

                  Something like:

                      scheduleComponent.createObject(scheduleCreate, {"prop1": prop1Val, "prop2": prop2Val, ...})
                  

                  I don't know if that's the correct parent for your case and of course you might not want to set any initial properties, in which case leave out the second argument. (Edit: looking more closely at your example, you don't seem to set any properties, but I guess you might have simplified it compared with the real thing.)

                  M Offline
                  M Offline
                  mzimmers
                  wrote on 21 Feb 2024, 22:03 last edited by
                  #7

                  @Bob64 yep, that works. I chose not to parent the object -- I believe this will cause it to be destroyed when this file goes out of scope.

                  property Schedule schedule
                  property Schedule scheduleCopy
                  Component {
                      id: scheduleComponent
                      Schedule {
                          id: newSchedule
                      }
                  }
                  
                  Component.onCompleted: {
                      if (schedule !== null) {
                          scheduleCopy = schedule.cloneSchedule(schedule)
                      } else {
                          scheduleCopy = scheduleComponent.createObject()
                      }
                  }
                  

                  Thanks for the help.

                  1 Reply Last reply
                  0
                  • M mzimmers has marked this topic as solved on 21 Feb 2024, 22:03
                  • M mzimmers referenced this topic on 25 Apr 2024, 01:35

                  1/7

                  21 Feb 2024, 16:08

                  • Login

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