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. accessing aggregates (QVector of a struct)

accessing aggregates (QVector of a struct)

Scheduled Pinned Locked Moved Solved QML and Qt Quick
52 Posts 4 Posters 6.7k 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.
  • K Offline
    K Offline
    kshegunov
    Moderators
    wrote on 6 Mar 2021, 00:46 last edited by kshegunov 3 Jun 2021, 01:07
    #28

    Okay, so here you go:

    types.h

    #ifndef TYPES_H
    #define TYPES_H
    
    #include <QObject>
    #include <QVector>
    #include <QVariant>
    #include <QVariantList>
    
    struct Bottle
    {
        Q_GADGET
    
        Q_PROPERTY(QString name MEMBER m_name)
        Q_PROPERTY(qreal size MEMBER m_size)
    
    public:
        QString m_name;
        qreal m_size;
    };
    
    class DataSource : public QObject
    {
        Q_OBJECT
    
    public:
        Q_INVOKABLE QVariantList getData();
    };
    
    
    #endif // TYPES_H
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    
    #include "types.h"
    
    QVariantList DataSource::getData()
    {
        return {
            QVariant::fromValue<Bottle>({ "First bottle", 0.75 }),
            QVariant::fromValue<Bottle>({ "Second bottle", 0.70 })
        };
    }
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        engine.addImportPath(QStringLiteral("qrc:/"));
        QUrl url(QStringLiteral("qrc:/main.qml"));
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url] (QObject * obj, const QUrl & objUrl) -> void {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);
    
        DataSource source;
        engine.rootContext()->setContextProperty(QStringLiteral("DataSource"), &source);
    
        qmlRegisterUncreatableType<Bottle>("Example", 1, 0, "Bottle", "");
    
        engine.load(url);
    
        return app.exec();
    }
    

    main.qml

    import QtQuick 2.15
    import QtQuick.Window 2.15
    import QtQuick.Controls 2.15
    
    import Example 1.0
    
    Window {
        id: mainWindow
        visible: true
        width: 300
        height: 200
        title: qsTr("Some title")
    
        Component {
            id: template
            Text {
                text: "defaultText"
            }
        }
    
        Column {
           Component.onCompleted: DataSource.getData().forEach(function(element) {
               template.createObject(this, { text: element.name });
           }, this)
        }
    }
    

    PS. QML is damn annoying ...

    Read and abide by the Qt Code of Conduct

    M 1 Reply Last reply 8 Mar 2021, 17:18
    1
    • K kshegunov
      6 Mar 2021, 00:46

      Okay, so here you go:

      types.h

      #ifndef TYPES_H
      #define TYPES_H
      
      #include <QObject>
      #include <QVector>
      #include <QVariant>
      #include <QVariantList>
      
      struct Bottle
      {
          Q_GADGET
      
          Q_PROPERTY(QString name MEMBER m_name)
          Q_PROPERTY(qreal size MEMBER m_size)
      
      public:
          QString m_name;
          qreal m_size;
      };
      
      class DataSource : public QObject
      {
          Q_OBJECT
      
      public:
          Q_INVOKABLE QVariantList getData();
      };
      
      
      #endif // TYPES_H
      

      main.cpp

      #include <QGuiApplication>
      #include <QQmlApplicationEngine>
      #include <QQmlContext>
      
      #include "types.h"
      
      QVariantList DataSource::getData()
      {
          return {
              QVariant::fromValue<Bottle>({ "First bottle", 0.75 }),
              QVariant::fromValue<Bottle>({ "Second bottle", 0.70 })
          };
      }
      
      int main(int argc, char *argv[])
      {
          QGuiApplication app(argc, argv);
      
          QQmlApplicationEngine engine;
          engine.addImportPath(QStringLiteral("qrc:/"));
          QUrl url(QStringLiteral("qrc:/main.qml"));
          QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url] (QObject * obj, const QUrl & objUrl) -> void {
              if (!obj && url == objUrl)
                  QCoreApplication::exit(-1);
          }, Qt::QueuedConnection);
      
          DataSource source;
          engine.rootContext()->setContextProperty(QStringLiteral("DataSource"), &source);
      
          qmlRegisterUncreatableType<Bottle>("Example", 1, 0, "Bottle", "");
      
          engine.load(url);
      
          return app.exec();
      }
      

      main.qml

      import QtQuick 2.15
      import QtQuick.Window 2.15
      import QtQuick.Controls 2.15
      
      import Example 1.0
      
      Window {
          id: mainWindow
          visible: true
          width: 300
          height: 200
          title: qsTr("Some title")
      
          Component {
              id: template
              Text {
                  text: "defaultText"
              }
          }
      
          Column {
             Component.onCompleted: DataSource.getData().forEach(function(element) {
                 template.createObject(this, { text: element.name });
             }, this)
          }
      }
      

      PS. QML is damn annoying ...

      M Offline
      M Offline
      mzimmers
      wrote on 8 Mar 2021, 17:18 last edited by
      #29

      @kshegunov said in accessing aggregates (QVector of a struct):

      PS. QML is damn annoying ...

      Heh...no argument there, but if I'm reading the tea leaves correctly, it's here to stay.

      I understand your C++ code, but I'm still trying to figure out what your QML results in. What exactly is this doing?

      Component {
              id: template
              Text {
                  text: "defaultText"
              }
          }
      
          Column {
             Component.onCompleted: DataSource.getData().forEach(function(element) {
                 template.createObject(this, { text: element.name });
             }, this)
          }
      
      K 1 Reply Last reply 8 Mar 2021, 19:20
      0
      • M mzimmers
        8 Mar 2021, 17:18

        @kshegunov said in accessing aggregates (QVector of a struct):

        PS. QML is damn annoying ...

        Heh...no argument there, but if I'm reading the tea leaves correctly, it's here to stay.

        I understand your C++ code, but I'm still trying to figure out what your QML results in. What exactly is this doing?

        Component {
                id: template
                Text {
                    text: "defaultText"
                }
            }
        
            Column {
               Component.onCompleted: DataSource.getData().forEach(function(element) {
                   template.createObject(this, { text: element.name });
               }, this)
            }
        
        K Offline
        K Offline
        kshegunov
        Moderators
        wrote on 8 Mar 2021, 19:20 last edited by kshegunov 3 Aug 2021, 19:26
        #30

        @mzimmers said in accessing aggregates (QVector of a struct):

        I understand your C++ code, but I'm still trying to figure out what your QML results in. What exactly is this doing?

        Well, I'm leveraging the fact that the QML engine is a glorified object factory. You know the widgets' basics, so with QtQuick it's the same story, more or less. It goes roughly like this:

        1. All visual items are derived from QQuickItem, these include the stuff you see in the QML file definition like Text and Column.
        2. Component does not(!) derive from QQuickItem, it is a QObject (or rather QQmlComponent) that's supposed to create your QQuickItems by calling QQmlComponent::createObject and passing it the correct visual parent and maybe a set of property values.
        3. When you load a QML file, this is what the engine does - it reads and instantiates the component your file represents, hence it creates all the visual and non-visual items described in said file. It parents everything by the way the items are nested (think of it as a big QObject tree). All the visual items are (re)parented to the root QQuickItem so they get painted correctly.
        4. After the object tree's loaded and the objects are instantiated you get the completed signal emitted and propagated through your items (visual and non-visual), so you can do w/e.
        5. In the above code you attach to the completed signal, then you call the getData to retrieve the list of structs, then forEach of the elements of the array you execute the anonymous function. The function is a dummy mostly. It just needs to go get the reference to the template component (which isn't a visual item, as mentioned) and call it's createObject to create the Text item contained. The first argument of the method is the visual parent (which is the Column in this case) and the second parameter is the set of properties to pass along, which is just the text value retrieved from the structure.

        PS. This code's tested (unlike most of the snippets I provide) so you can directly plug it in your project/app and play with it as you wish.

        Read and abide by the Qt Code of Conduct

        M 1 Reply Last reply 8 Mar 2021, 19:49
        2
        • K kshegunov
          8 Mar 2021, 19:20

          @mzimmers said in accessing aggregates (QVector of a struct):

          I understand your C++ code, but I'm still trying to figure out what your QML results in. What exactly is this doing?

          Well, I'm leveraging the fact that the QML engine is a glorified object factory. You know the widgets' basics, so with QtQuick it's the same story, more or less. It goes roughly like this:

          1. All visual items are derived from QQuickItem, these include the stuff you see in the QML file definition like Text and Column.
          2. Component does not(!) derive from QQuickItem, it is a QObject (or rather QQmlComponent) that's supposed to create your QQuickItems by calling QQmlComponent::createObject and passing it the correct visual parent and maybe a set of property values.
          3. When you load a QML file, this is what the engine does - it reads and instantiates the component your file represents, hence it creates all the visual and non-visual items described in said file. It parents everything by the way the items are nested (think of it as a big QObject tree). All the visual items are (re)parented to the root QQuickItem so they get painted correctly.
          4. After the object tree's loaded and the objects are instantiated you get the completed signal emitted and propagated through your items (visual and non-visual), so you can do w/e.
          5. In the above code you attach to the completed signal, then you call the getData to retrieve the list of structs, then forEach of the elements of the array you execute the anonymous function. The function is a dummy mostly. It just needs to go get the reference to the template component (which isn't a visual item, as mentioned) and call it's createObject to create the Text item contained. The first argument of the method is the visual parent (which is the Column in this case) and the second parameter is the set of properties to pass along, which is just the text value retrieved from the structure.

          PS. This code's tested (unlike most of the snippets I provide) so you can directly plug it in your project/app and play with it as you wish.

          M Offline
          M Offline
          mzimmers
          wrote on 8 Mar 2021, 19:49 last edited by
          #31

          @kshegunov OK, I think I understand 1-4. But where is the getData() function explicitly referenced/called? (I think your getData() is the equivalent to my QVariantList BottleList::getBottleListQv().)

          I still don't understand how to retrieve the information to use it in my bottle objects.

                  Bottle {
                      id: bottle1
                      cellX: 25
                      cellY: 105
                      cellHeight: 75
                      cellWidth: 75
                      bottleScaleFactor: scaleFactor
                      cellText: "W7" // how to replace this with something from getData()?
                      cellColor: "red"
                  }
          

          Thanks...

          O K 2 Replies Last reply 8 Mar 2021, 20:53
          0
          • M mzimmers
            8 Mar 2021, 19:49

            @kshegunov OK, I think I understand 1-4. But where is the getData() function explicitly referenced/called? (I think your getData() is the equivalent to my QVariantList BottleList::getBottleListQv().)

            I still don't understand how to retrieve the information to use it in my bottle objects.

                    Bottle {
                        id: bottle1
                        cellX: 25
                        cellY: 105
                        cellHeight: 75
                        cellWidth: 75
                        bottleScaleFactor: scaleFactor
                        cellText: "W7" // how to replace this with something from getData()?
                        cellColor: "red"
                    }
            

            Thanks...

            O Offline
            O Offline
            ODБOï
            wrote on 8 Mar 2021, 20:53 last edited by
            #32

            hi

            @mzimmers said in accessing aggregates (QVector of a struct):

            I still don't understand how to retrieve the information to use it in my bottle objects.

            the answer is

            @kshegunov said in accessing aggregates (QVector of a struct):

            In the above code you attach to the completed signal, then you call the getData to retrieve the list of structs, then forEach of the elements of the array you execute the anonymous function. The function is a dummy mostly. It just needs to go get the reference to the template component (which isn't a visual item, as mentioned) and call it's createObject to create the Text item contained. The first argument of the method is the visual parent (which is the Column in this case) and the second parameter is the set of properties to pass along, which is just the text value retrieved from the structure.

             Column {
                   Component.onCompleted: 
                
                    DataSource.getData().forEach(function(element) {//anonymous  function call for each object  returned by  getData()
                     
                       template.createObject(this, { text: element.name }); // create a qml object  using the template and pass  the value retrieved from the structure  ( text:element.name )
                   }, this)
                }
            

            Please make an empty project and test one of the examples given by @kshegunov @fcarney or me

            M 1 Reply Last reply 8 Mar 2021, 21:32
            0
            • O ODБOï
              8 Mar 2021, 20:53

              hi

              @mzimmers said in accessing aggregates (QVector of a struct):

              I still don't understand how to retrieve the information to use it in my bottle objects.

              the answer is

              @kshegunov said in accessing aggregates (QVector of a struct):

              In the above code you attach to the completed signal, then you call the getData to retrieve the list of structs, then forEach of the elements of the array you execute the anonymous function. The function is a dummy mostly. It just needs to go get the reference to the template component (which isn't a visual item, as mentioned) and call it's createObject to create the Text item contained. The first argument of the method is the visual parent (which is the Column in this case) and the second parameter is the set of properties to pass along, which is just the text value retrieved from the structure.

               Column {
                     Component.onCompleted: 
                  
                      DataSource.getData().forEach(function(element) {//anonymous  function call for each object  returned by  getData()
                       
                         template.createObject(this, { text: element.name }); // create a qml object  using the template and pass  the value retrieved from the structure  ( text:element.name )
                     }, this)
                  }
              

              Please make an empty project and test one of the examples given by @kshegunov @fcarney or me

              M Offline
              M Offline
              mzimmers
              wrote on 8 Mar 2021, 21:32 last edited by
              #33

              @LeLev (et al): kshugenov's example does indeed work. I tried modifying it as follows:

                  Column {
                     property var myArray: []
                     Component.onCompleted: DataSource.getData().forEach(function(bottle) {
              //           template.createObject(this, { text: bottle.name });
                         myArray.push(bottle.name)
                     }, this)
                  Text {
                      text: myArray[0]
                  }
              

              But I get a runtime error that myArray is not defined. Am I supposed to use something other than a property var for this?

              Thanks...

              O 1 Reply Last reply 8 Mar 2021, 21:45
              0
              • M mzimmers
                8 Mar 2021, 21:32

                @LeLev (et al): kshugenov's example does indeed work. I tried modifying it as follows:

                    Column {
                       property var myArray: []
                       Component.onCompleted: DataSource.getData().forEach(function(bottle) {
                //           template.createObject(this, { text: bottle.name });
                           myArray.push(bottle.name)
                       }, this)
                    Text {
                        text: myArray[0]
                    }
                

                But I get a runtime error that myArray is not defined. Am I supposed to use something other than a property var for this?

                Thanks...

                O Offline
                O Offline
                ODБOï
                wrote on 8 Mar 2021, 21:45 last edited by ODБOï 3 Aug 2021, 21:50
                #34

                @mzimmers said in accessing aggregates (QVector of a struct):

                myArray is not defined

                you need to assign the id of Column so you can access its properties from outside, it is qml basics

                Column {
                id :col
                property var myArray: []
                Text {
                text: col.myArray[0]
                }
                }

                @mzimmers said in accessing aggregates (QVector of a struct):

                kshugenov's example does indeed work.

                it does almost exactly the same thing as my very first example/answer.

                M 1 Reply Last reply 8 Mar 2021, 21:52
                1
                • O ODБOï
                  8 Mar 2021, 21:45

                  @mzimmers said in accessing aggregates (QVector of a struct):

                  myArray is not defined

                  you need to assign the id of Column so you can access its properties from outside, it is qml basics

                  Column {
                  id :col
                  property var myArray: []
                  Text {
                  text: col.myArray[0]
                  }
                  }

                  @mzimmers said in accessing aggregates (QVector of a struct):

                  kshugenov's example does indeed work.

                  it does almost exactly the same thing as my very first example/answer.

                  M Offline
                  M Offline
                  mzimmers
                  wrote on 8 Mar 2021, 21:52 last edited by mzimmers 3 Aug 2021, 21:58
                  #35

                  @LeLev ah. So, now my code looks like this:

                      Column {
                          id: myColumn
                          property var myArray: []
                          Component.onCompleted: DataSource.getData().forEach(function(bottle) {
                              //           template.createObject(this, { text: bottle.name });
                              myArray.push(bottle.name)
                          }, this)
                          Text {
                              text: myColumn.myArray[0]
                          }
                          Text {
                              text:myColumn.myArray[1]
                          }
                          Text {
                              text: myColumn.myArray[2]
                          }
                      }
                  

                  and I'm getting this error: "Unable to assign [undefined] to QString"

                  EDIT: I've stepped through this in the debugger, and the array is most definitely being created.

                  O 1 Reply Last reply 8 Mar 2021, 22:10
                  1
                  • M mzimmers
                    8 Mar 2021, 21:52

                    @LeLev ah. So, now my code looks like this:

                        Column {
                            id: myColumn
                            property var myArray: []
                            Component.onCompleted: DataSource.getData().forEach(function(bottle) {
                                //           template.createObject(this, { text: bottle.name });
                                myArray.push(bottle.name)
                            }, this)
                            Text {
                                text: myColumn.myArray[0]
                            }
                            Text {
                                text:myColumn.myArray[1]
                            }
                            Text {
                                text: myColumn.myArray[2]
                            }
                        }
                    

                    and I'm getting this error: "Unable to assign [undefined] to QString"

                    EDIT: I've stepped through this in the debugger, and the array is most definitely being created.

                    O Offline
                    O Offline
                    ODБOï
                    wrote on 8 Mar 2021, 22:10 last edited by ODБOï 3 Aug 2021, 22:14
                    #36

                    @mzimmers said in accessing aggregates (QVector of a struct):

                    Column {
                    id: myColumn
                    property var myArray: []
                    Component.onCompleted: DataSource.getData().forEach(function(bottle) {
                    // template.createObject(this, { text: bottle.name });
                    myArray.push(bottle.name)
                    }, this)

                    you should not modify myArray directly in the function but create a local array then copy its content into myArray

                    Column {
                            id: myColumn
                            property var myArray: []
                            Component.onCompleted: {
                               var arr = []
                               DataSource.getData().forEach(function(bottle) {           
                                //myArray.push(bottle.name)
                                  arr.push(bottle.name)
                            }, this);
                          myColumn.myArray = arr;          
                    }
                    
                    M 1 Reply Last reply 8 Mar 2021, 22:26
                    3
                    • O ODБOï
                      8 Mar 2021, 22:10

                      @mzimmers said in accessing aggregates (QVector of a struct):

                      Column {
                      id: myColumn
                      property var myArray: []
                      Component.onCompleted: DataSource.getData().forEach(function(bottle) {
                      // template.createObject(this, { text: bottle.name });
                      myArray.push(bottle.name)
                      }, this)

                      you should not modify myArray directly in the function but create a local array then copy its content into myArray

                      Column {
                              id: myColumn
                              property var myArray: []
                              Component.onCompleted: {
                                 var arr = []
                                 DataSource.getData().forEach(function(bottle) {           
                                  //myArray.push(bottle.name)
                                    arr.push(bottle.name)
                              }, this);
                            myColumn.myArray = arr;          
                      }
                      
                      M Offline
                      M Offline
                      mzimmers
                      wrote on 8 Mar 2021, 22:26 last edited by
                      #37

                      @LeLev that works! Thanks for your patience on this.

                      May I ask why my approach didn't work?

                      O 1 Reply Last reply 8 Mar 2021, 22:34
                      0
                      • M mzimmers
                        8 Mar 2021, 22:26

                        @LeLev that works! Thanks for your patience on this.

                        May I ask why my approach didn't work?

                        O Offline
                        O Offline
                        ODБOï
                        wrote on 8 Mar 2021, 22:34 last edited by ODБOï 3 Aug 2021, 22:53
                        #38

                        @mzimmers
                        here is an example to illustrate, uncomment one or the other Component.onCompleted, you will observe that when we call
                        col.myArr.push("N° " + i) directly, the view is empty at the beginning but myArr actually contains the items

                        Window {
                            width: 640
                            height: 480
                            visible: true
                        
                            Column{
                                id:col
                                property var myArr : []
                        
                        // calling myArr.push() directly in the function.
                        //   You will need to somehow "refresh" the view, (in this example see the button that resets the repeater model)
                                
                        //        Component.onCompleted: {
                        //            var arr = []
                        //            for(var i=0;i<10;i++){
                        //                col.myArr.push("N° " + i)
                        //            }
                        //        }
                        //OR ------------------------------------------
                        // creating a local array        
                                
                        //        Component.onCompleted: {
                        //            var arr = []
                        //            for(var i=0;i<10;i++){
                        //                arr.push("N° " + i)
                        //            }
                        //            col.myArr = arr;
                        //        }
                        
                                //--------------------------------------------------
                                Repeater{
                                    id:rep
                                    model: col.myArr.length
                        
                                    Text {
                                        id: txt
                                        text: col.myArr[index]
                                    }
                                }
                                //--------------------------------------------------
                                Button{ 
                                    text: 'refresh'
                                    onClicked:{ rep.model = 0; rep.model = col.myArr.length;  console.log(col.myArr) } // just to reset the repeater
                                }
                            }
                        }
                        

                        It's great that your solution worked but why not implement something where you can simply write

                         Text {
                                    text: DataSource.getDataByIndex(0).name 
                                }
                        
                        M 1 Reply Last reply 8 Mar 2021, 23:03
                        0
                        • O ODБOï
                          8 Mar 2021, 22:34

                          @mzimmers
                          here is an example to illustrate, uncomment one or the other Component.onCompleted, you will observe that when we call
                          col.myArr.push("N° " + i) directly, the view is empty at the beginning but myArr actually contains the items

                          Window {
                              width: 640
                              height: 480
                              visible: true
                          
                              Column{
                                  id:col
                                  property var myArr : []
                          
                          // calling myArr.push() directly in the function.
                          //   You will need to somehow "refresh" the view, (in this example see the button that resets the repeater model)
                                  
                          //        Component.onCompleted: {
                          //            var arr = []
                          //            for(var i=0;i<10;i++){
                          //                col.myArr.push("N° " + i)
                          //            }
                          //        }
                          //OR ------------------------------------------
                          // creating a local array        
                                  
                          //        Component.onCompleted: {
                          //            var arr = []
                          //            for(var i=0;i<10;i++){
                          //                arr.push("N° " + i)
                          //            }
                          //            col.myArr = arr;
                          //        }
                          
                                  //--------------------------------------------------
                                  Repeater{
                                      id:rep
                                      model: col.myArr.length
                          
                                      Text {
                                          id: txt
                                          text: col.myArr[index]
                                      }
                                  }
                                  //--------------------------------------------------
                                  Button{ 
                                      text: 'refresh'
                                      onClicked:{ rep.model = 0; rep.model = col.myArr.length;  console.log(col.myArr) } // just to reset the repeater
                                  }
                              }
                          }
                          

                          It's great that your solution worked but why not implement something where you can simply write

                           Text {
                                      text: DataSource.getDataByIndex(0).name 
                                  }
                          
                          M Offline
                          M Offline
                          mzimmers
                          wrote on 8 Mar 2021, 23:03 last edited by
                          #39

                          @LeLev I may have spoken a bit too soon...when I try to apply this from the example to my application, I get the error again.

                          Column {
                          	id: myColumn
                          	property var myArray: []
                          	Component.onCompleted: {
                          		var arr = []
                          		BottleList.getBottleListQv().forEach(function(bottle) {
                          			arr.push(bottle.name)
                          		}, this);
                          		myColumn.myArray = arr;
                          	}
                          
                          	Bottle {
                          		cellText: myColumn.myArray[0]//"W7"
                          	}
                          

                          The array element notation seems like it's correct; can you see what I'm doing wrong?

                          Regarding writing a function for the name: I would do that, and I still may, but I want to grow this to return several values in the struct: name, position, capacity, fill level, etc. So far, this approach looks better for that.

                          O K 2 Replies Last reply 8 Mar 2021, 23:16
                          0
                          • M mzimmers
                            8 Mar 2021, 23:03

                            @LeLev I may have spoken a bit too soon...when I try to apply this from the example to my application, I get the error again.

                            Column {
                            	id: myColumn
                            	property var myArray: []
                            	Component.onCompleted: {
                            		var arr = []
                            		BottleList.getBottleListQv().forEach(function(bottle) {
                            			arr.push(bottle.name)
                            		}, this);
                            		myColumn.myArray = arr;
                            	}
                            
                            	Bottle {
                            		cellText: myColumn.myArray[0]//"W7"
                            	}
                            

                            The array element notation seems like it's correct; can you see what I'm doing wrong?

                            Regarding writing a function for the name: I would do that, and I still may, but I want to grow this to return several values in the struct: name, position, capacity, fill level, etc. So far, this approach looks better for that.

                            O Offline
                            O Offline
                            ODБOï
                            wrote on 8 Mar 2021, 23:16 last edited by ODБOï 3 Aug 2021, 23:24
                            #40

                            @mzimmers said in accessing aggregates (QVector of a struct):

                            I get the error again.

                            what error do you get ? Did you read/test my example with all the comments about the arrays, i think the error you get is related to that

                            1 Reply Last reply
                            0
                            • M mzimmers
                              8 Mar 2021, 23:03

                              @LeLev I may have spoken a bit too soon...when I try to apply this from the example to my application, I get the error again.

                              Column {
                              	id: myColumn
                              	property var myArray: []
                              	Component.onCompleted: {
                              		var arr = []
                              		BottleList.getBottleListQv().forEach(function(bottle) {
                              			arr.push(bottle.name)
                              		}, this);
                              		myColumn.myArray = arr;
                              	}
                              
                              	Bottle {
                              		cellText: myColumn.myArray[0]//"W7"
                              	}
                              

                              The array element notation seems like it's correct; can you see what I'm doing wrong?

                              Regarding writing a function for the name: I would do that, and I still may, but I want to grow this to return several values in the struct: name, position, capacity, fill level, etc. So far, this approach looks better for that.

                              K Offline
                              K Offline
                              kshegunov
                              Moderators
                              wrote on 8 Mar 2021, 23:24 last edited by
                              #41

                              @mzimmers said in accessing aggregates (QVector of a struct):

                              @LeLev I may have spoken a bit too soon...when I try to apply this from the example to my application, I get the error again.

                              At the time you reference the array it's empty. That's the reason. Component.onCompleted is executed after the property to Bottle.cellText is bound, so the JS engine throws you an error, there's no such thing as myArray[0] at this point; the array is empty.

                              Read and abide by the Qt Code of Conduct

                              M 1 Reply Last reply 9 Mar 2021, 00:03
                              2
                              • M mzimmers
                                8 Mar 2021, 19:49

                                @kshegunov OK, I think I understand 1-4. But where is the getData() function explicitly referenced/called? (I think your getData() is the equivalent to my QVariantList BottleList::getBottleListQv().)

                                I still don't understand how to retrieve the information to use it in my bottle objects.

                                        Bottle {
                                            id: bottle1
                                            cellX: 25
                                            cellY: 105
                                            cellHeight: 75
                                            cellWidth: 75
                                            bottleScaleFactor: scaleFactor
                                            cellText: "W7" // how to replace this with something from getData()?
                                            cellColor: "red"
                                        }
                                

                                Thanks...

                                K Offline
                                K Offline
                                kshegunov
                                Moderators
                                wrote on 8 Mar 2021, 23:31 last edited by kshegunov 3 Aug 2021, 23:34
                                #42

                                @mzimmers said in accessing aggregates (QVector of a struct):

                                I still don't understand how to retrieve the information to use it in my bottle objects.

                                You can instantiate them at runtime (as I did with the text item), you just need to replace the Text with your template for the Bottle. Alternatively you can use the Repeater @LeLev's been pushing, but then set the delegate property to a component which is going to create your bottle items (the repeater with a set delegate pretty much does what my example does). Note I don't know if the model property is going to work with a list of gadgets, you need to check.

                                @LeLev said in accessing aggregates (QVector of a struct):

                                it does almost exactly the same thing as my very first example/answer.

                                Almost but with fewer objects created under the hood. Not that it really matters as the QML engine is an elephant anyway.

                                Read and abide by the Qt Code of Conduct

                                O 1 Reply Last reply 9 Mar 2021, 00:01
                                0
                                • K kshegunov
                                  8 Mar 2021, 23:31

                                  @mzimmers said in accessing aggregates (QVector of a struct):

                                  I still don't understand how to retrieve the information to use it in my bottle objects.

                                  You can instantiate them at runtime (as I did with the text item), you just need to replace the Text with your template for the Bottle. Alternatively you can use the Repeater @LeLev's been pushing, but then set the delegate property to a component which is going to create your bottle items (the repeater with a set delegate pretty much does what my example does). Note I don't know if the model property is going to work with a list of gadgets, you need to check.

                                  @LeLev said in accessing aggregates (QVector of a struct):

                                  it does almost exactly the same thing as my very first example/answer.

                                  Almost but with fewer objects created under the hood. Not that it really matters as the QML engine is an elephant anyway.

                                  O Offline
                                  O Offline
                                  ODБOï
                                  wrote on 9 Mar 2021, 00:01 last edited by ODБOï 3 Sept 2021, 00:02
                                  #43

                                  @kshegunov said in accessing aggregates (QVector of a struct):

                                  Alternatively you can use the Repeater @LeLev's been pushing

                                  I just use a Repeater to answer to this question :

                                  @mzimmers said in accessing aggregates (QVector of a struct):

                                  @LeLev ah. So, now my code looks like this:
                                  Column {
                                  id: myColumn
                                  property var myArray: []
                                  Component.onCompleted: DataSource.getData().forEach(function(bottle) {
                                  // template.createObject(this, { text: bottle.name });
                                  myArray.push(bottle.name)
                                  }, this)
                                  Text {
                                  text: myColumn.myArray[0]
                                  }
                                  Text {
                                  text:myColumn.myArray[1]
                                  }
                                  Text {
                                  text: myColumn.myArray[2]
                                  }
                                  }

                                  just shorter to write with a repeater
                                  i'm really not pushing mzimmers to use it. it was just an example to show what is happening with "property var myArray: []" initialisation

                                  M K 2 Replies Last reply 9 Mar 2021, 00:07
                                  0
                                  • K kshegunov
                                    8 Mar 2021, 23:24

                                    @mzimmers said in accessing aggregates (QVector of a struct):

                                    @LeLev I may have spoken a bit too soon...when I try to apply this from the example to my application, I get the error again.

                                    At the time you reference the array it's empty. That's the reason. Component.onCompleted is executed after the property to Bottle.cellText is bound, so the JS engine throws you an error, there's no such thing as myArray[0] at this point; the array is empty.

                                    M Offline
                                    M Offline
                                    mzimmers
                                    wrote on 9 Mar 2021, 00:03 last edited by
                                    #44

                                    @kshegunov said in accessing aggregates (QVector of a struct):

                                    @mzimmers said in accessing aggregates (QVector of a struct):

                                    @LeLev I may have spoken a bit too soon...when I try to apply this from the example to my application, I get the error again.

                                    At the time you reference the array it's empty. That's the reason. Component.onCompleted is executed after the property to Bottle.cellText is bound, so the JS engine throws you an error, there's no such thing as myArray[0] at this point; the array is empty.

                                    That makes sense. So, according to the docs, I can use the onCompleted() handler with any object. Can I somehow use it with my Bottle (defined in QML) object?

                                    1 Reply Last reply
                                    0
                                    • O ODБOï
                                      9 Mar 2021, 00:01

                                      @kshegunov said in accessing aggregates (QVector of a struct):

                                      Alternatively you can use the Repeater @LeLev's been pushing

                                      I just use a Repeater to answer to this question :

                                      @mzimmers said in accessing aggregates (QVector of a struct):

                                      @LeLev ah. So, now my code looks like this:
                                      Column {
                                      id: myColumn
                                      property var myArray: []
                                      Component.onCompleted: DataSource.getData().forEach(function(bottle) {
                                      // template.createObject(this, { text: bottle.name });
                                      myArray.push(bottle.name)
                                      }, this)
                                      Text {
                                      text: myColumn.myArray[0]
                                      }
                                      Text {
                                      text:myColumn.myArray[1]
                                      }
                                      Text {
                                      text: myColumn.myArray[2]
                                      }
                                      }

                                      just shorter to write with a repeater
                                      i'm really not pushing mzimmers to use it. it was just an example to show what is happening with "property var myArray: []" initialisation

                                      M Offline
                                      M Offline
                                      mzimmers
                                      wrote on 9 Mar 2021, 00:07 last edited by
                                      #45

                                      @LeLev it's a good suggestion; I'm still looking at the code.

                                      I probably don't really need the Column any more, as far as that goes. But I guess I need something to attach the Component.onCompleted() to.

                                      1 Reply Last reply
                                      0
                                      • O ODБOï
                                        9 Mar 2021, 00:01

                                        @kshegunov said in accessing aggregates (QVector of a struct):

                                        Alternatively you can use the Repeater @LeLev's been pushing

                                        I just use a Repeater to answer to this question :

                                        @mzimmers said in accessing aggregates (QVector of a struct):

                                        @LeLev ah. So, now my code looks like this:
                                        Column {
                                        id: myColumn
                                        property var myArray: []
                                        Component.onCompleted: DataSource.getData().forEach(function(bottle) {
                                        // template.createObject(this, { text: bottle.name });
                                        myArray.push(bottle.name)
                                        }, this)
                                        Text {
                                        text: myColumn.myArray[0]
                                        }
                                        Text {
                                        text:myColumn.myArray[1]
                                        }
                                        Text {
                                        text: myColumn.myArray[2]
                                        }
                                        }

                                        just shorter to write with a repeater
                                        i'm really not pushing mzimmers to use it. it was just an example to show what is happening with "property var myArray: []" initialisation

                                        K Offline
                                        K Offline
                                        kshegunov
                                        Moderators
                                        wrote on 9 Mar 2021, 00:22 last edited by
                                        #46

                                        @LeLev said in accessing aggregates (QVector of a struct):

                                        i'm really not pushing mzimmers to use it. it was just an example to show what is happening with "property var myArray: []" initialisation

                                        That came out badly. I didn't mean to imply it's wrong in any way, or that your answer is bad. A poor choice of words, sorry.

                                        @mzimmers said in accessing aggregates (QVector of a struct):

                                        That makes sense. So, according to the docs, I can use the onCompleted() handler with any object. Can I somehow use it with my Bottle (defined in QML) object?

                                        Yes all the items can attach to it. Think of it as a "global" signal (sort of).

                                        Read and abide by the Qt Code of Conduct

                                        O 1 Reply Last reply 9 Mar 2021, 00:25
                                        1
                                        • K kshegunov
                                          9 Mar 2021, 00:22

                                          @LeLev said in accessing aggregates (QVector of a struct):

                                          i'm really not pushing mzimmers to use it. it was just an example to show what is happening with "property var myArray: []" initialisation

                                          That came out badly. I didn't mean to imply it's wrong in any way, or that your answer is bad. A poor choice of words, sorry.

                                          @mzimmers said in accessing aggregates (QVector of a struct):

                                          That makes sense. So, according to the docs, I can use the onCompleted() handler with any object. Can I somehow use it with my Bottle (defined in QML) object?

                                          Yes all the items can attach to it. Think of it as a "global" signal (sort of).

                                          O Offline
                                          O Offline
                                          ODБOï
                                          wrote on 9 Mar 2021, 00:25 last edited by ODБOï 3 Sept 2021, 00:28
                                          #47

                                          @kshegunov no worries , i just wanted to clarify

                                          @mzimmers said in accessing aggregates (QVector of a struct):

                                          Can I somehow use it with my Bottle (defined in QML) object?

                                          you can refactor the code in the Component.onCompleted into a function and call it when you need

                                          M 1 Reply Last reply 9 Mar 2021, 00:32
                                          0

                                          37/52

                                          8 Mar 2021, 22:26

                                          • Login

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