Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Is there a way to make QML use 2D data model ?
Qt 6.12 LTS is out! See what's new in the release blog

Is there a way to make QML use 2D data model ?

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
14 Posts 3 Posters 365 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.
  • SGaistS SGaist

    Hi,

    Are you looking for something like described in the QAbstractItemModel Subclass in the Using C++ Models with Qt Quick Views chapter of Qt's documentation ?

    GilboonetG Offline
    GilboonetG Offline
    Gilboonet
    wrote last edited by
    #3

    @SGaist Thank you, I'm going to try that as replacement of QAbstractListModel, I've found an example QML project using that class, apparently there's need to use role. I will post my progress.

    1 Reply Last reply
    0
    • GilboonetG Offline
      GilboonetG Offline
      Gilboonet
      wrote last edited by Gilboonet
      #4

      I'm trying to use QRangeModel as it seems to be a very neat feature.

      I start a new QML Project, add a C++ class to it, instance my class on the main.cpp main() to create my data, create a QRangeModel using the data, add a property with that QRangeModel, that I finally use as model on my QML file.

      For the moment I can only see on the QML side the QRangeModel as a QQmlListModel (from console.log on Component.onCompleted), but I don't see how to use its data.

      Here's my code :
      main.cpp

      #include <QGuiApplication>
      #include "piece.h"
      #include <QRangeModel>
      #include <QQmlApplicationEngine>
      #include <QVariant>
      
      int main(int argc, char *argv[])
      {
          QGuiApplication app(argc, argv);
      
          QList<Piece> mesPieces;
          mesPieces.append(Piece(20, 20));
          mesPieces.append(Piece(60, 0));
          QRangeModel modele(&mesPieces);
      
          QQmlApplicationEngine engine;
          engine.setInitialProperties({
              {"monModele", QVariant::fromValue(&modele)}
          });
      
          QObject::connect(
              &engine,
              &QQmlApplicationEngine::objectCreationFailed,
              &app,
              []() { QCoreApplication::exit(-1); },
              Qt::QueuedConnection);
          engine.loadFromModule("testDeleg2", "Main");
      
          return QGuiApplication::exec();
      }
      

      piece.h (class header)

      #ifndef PIECE_H
      #define PIECE_H
      
      #include <QtTypes>
      
      class Piece
      {
      public:
          qreal x, y;
          Piece() {};
          Piece(qreal px, qreal py) : x(px), y(py) {}
      
          void setX(const qreal newX) {m_x = newX;}
          void setY(const qreal newY) {m_y = newY;}
      
      private:
          qreal m_x;
          qreal m_y;
      };
      
      #endif // PIECE_H
      

      QML

      import QtQuick
      import QtQuick.Controls.Basic
      import QtQuick.Shapes
      
      ApplicationWindow {
          id: window
          width: 640
          height: 480
          minimumWidth: 200
          minimumHeight: 250
          visible: true
          title: qsTr("test QRangeModel")
      
          /*ListModel {
              id: monModele
              ListElement { x: 20 ; y: 20 }
              ListElement { x: 60 ; y: 0 }
          }*/
      
          required property AbstractItemModel monModele
      
          Repeater {
              model : monModele
              Shape {
                  anchors.fill: parent
      
              ShapePath {
                      strokeColor: "yellow"
                      fillColor: "yellow"
                      strokeWidth: 1
                      startX: model.x
                      startY: model.y
                      PathLine { relativeX: 0; relativeY: 50 }
                      PathLine { relativeX: 50; relativeY: 0 }
                  }
              }
              Component.onCompleted: {
                  console.log(monModele);
              }
          }
      }
      

      The ListModels contains what the QRangeModel is supposed to have.
      Maybe do I need to add getters ?

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

        I haven't used it in such a fashion yet but I think what you want is in the Structs and gadgets as rows chapter In QRangeModel's documentation.

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

        1 Reply Last reply
        1
        • GilboonetG Offline
          GilboonetG Offline
          Gilboonet
          wrote last edited by Gilboonet
          #6

          I changed my class, so now it's a Q_GADGET, having properties with getters (READ x and READ y), but even with Q_INVOKABLE, I can't use any of them on the QML side. When I run on debug with a breakpoint and inspect the QRangeModel, it does not seem to have the values, no children. I'm certainly missing something.

          1 Reply Last reply
          0
          • GilboonetG Offline
            GilboonetG Offline
            Gilboonet
            wrote last edited by
            #7

            To get my model data from QML, i needed to use data, giving it an index by using its index function and the Qt.DisplayRole.

                            startX: monModele.data(monModele.index(index,0), Qt.DisplayRole)
                            startY: monModele.data(monModele.index(index,1), Qt.DisplayRole)
            

            Now I'm adding the 2d data part.

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

              You should follow the following section to expose your properties as roles:
              https://doc.qt.io/qt-6/qrangemodel.html#gadgets-and-objects-as-multi-role-items

              You should then be able to write startY: model.y (with a required property QtObject model in the delegate)

              GilboonetG 1 Reply Last reply
              0
              • GrecKoG GrecKo

                You should follow the following section to expose your properties as roles:
                https://doc.qt.io/qt-6/qrangemodel.html#gadgets-and-objects-as-multi-role-items

                You should then be able to write startY: model.y (with a required property QtObject model in the delegate)

                GilboonetG Offline
                GilboonetG Offline
                Gilboonet
                wrote last edited by
                #9

                @GrecKo Thank you, I am using a Q_GADGET class but was missing the required property in the delegate for each property. Sadly adding the required property in the repeater is not enough. I tried to put it directly into the repeater after the model setting, there it is not initialized and get undefined as value.

                My gadget class is as basic as possible, but I'm not able to set it up correctly to be able to use properties name on the QML side. For the moment I'm sticking to the mymodel.data(...index(...), Qt.DisplayRole) that works.

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

                  Can you share a minimal compilable application with your current code ?
                  That would allow us to check what is going on.

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

                  1 Reply Last reply
                  0
                  • GilboonetG Offline
                    GilboonetG Offline
                    Gilboonet
                    wrote last edited by
                    #11

                    the data class

                    #ifndef PIECE_H
                    #define PIECE_H
                    
                    
                    #include <QtCore/qobjectdefs.h>
                    #include <QtCore/qtmetamacros.h>
                    class piece
                    {
                        Q_GADGET
                        Q_PROPERTY(float x READ x WRITE setX)
                        Q_PROPERTY(float y READ y WRITE setY)
                    
                    public:
                        piece() : m_x(0.0f), m_y(0.0f) {}
                        piece(const piece &) = default;
                        piece(piece &&) = default;
                        piece &operator=(const piece &) = default;
                        piece &operator=(piece &&) = default;
                        explicit piece(const float &x, const float &y) : m_x(x), m_y(y) {}
                    
                        void setX(float newX) {
                            if (!qFuzzyCompare(newX, m_x))
                                m_x = newX;
                        }
                        void setY(float newY) {
                            if (!qFuzzyCompare(newY, m_y))
                                m_y = newY;
                        }
                    
                    private:
                        float m_x;
                        float m_y;
                        float x() const { return m_x; }
                        float y() const { return m_y; }
                    };
                    
                    #endif // PIECE_H
                    

                    main.cpp

                    #include "piece.h"
                    #include <QRangeModel>
                    #include <QGuiApplication>
                    #include <QQmlApplicationEngine>
                    
                    int main(int argc, char *argv[])
                    {
                        QGuiApplication app(argc, argv);
                    
                        QList<piece> mesPieces;
                        mesPieces.append(piece(20.0f, 20.0f));
                        mesPieces.append(piece(60.0f, 0.0f));
                        mesPieces.append(piece(100.0f, 30.0f));
                        QRangeModel modele(&mesPieces);
                    
                        QQmlApplicationEngine engine;
                        engine.setInitialProperties({{"monModele", QVariant::fromValue(&modele) }});
                    
                        QObject::connect(
                            &engine,
                            &QQmlApplicationEngine::objectCreationFailed,
                            &app,
                            []() { QCoreApplication::exit(-1); },
                            Qt::QueuedConnection);
                        engine.loadFromModule("testQRange1", "Main");
                    
                        return QGuiApplication::exec();
                    }
                    

                    main.qml

                    import QtQuick
                    import QtQuick.Controls.Basic
                    import QtQuick.Shapes
                    
                    ApplicationWindow {
                        id: window
                        width: 640
                        height: 480
                        visible: true
                        title: qsTr("test QRangeModel")
                    
                        required property AbstractItemModel monModele
                    
                        Repeater {
                            model : monModele
                            Shape {
                                property real mx :   monModele.data(monModele.index(index, 0), Qt.DisplayRole)
                                property real my :   monModele.data(monModele.index(index, 1), Qt.DisplayRole)
                                anchors.fill: parent
                                ShapePath {
                                    strokeColor: "yellow"
                                    fillColor: "yellow"
                                    strokeWidth: 1
                                    startX: mx
                                    startY: my
                                    PathLine { relativeX: 0; relativeY: 50 }
                                    PathLine { relativeX: 50; relativeY: 0 }
                                }
                            }
                        }
                    }
                    

                    It doesn't work if I try to replace mx and my properties by required property real x (and y)

                    1 Reply Last reply
                    0
                    • GilboonetG Offline
                      GilboonetG Offline
                      Gilboonet
                      wrote last edited by
                      #12

                      I didn't dig that naming problem, but focused on my main goal here, to be able to create a 2d dataset, ,put it into my model and send that model to QML. To achieve that I added to my gadget class a property of QList<QPoint> type that can be used on QML side. Sadly apparently it can only be used by a repeater at the Shape level and not into a shape to build it by using repeater on its children, but it's somehow a progress for me compared to my current implementation that uses a QAbstractListItem that builds shapes PathSvg.

                      SGaistS 1 Reply Last reply
                      0
                      • GilboonetG Gilboonet

                        I didn't dig that naming problem, but focused on my main goal here, to be able to create a 2d dataset, ,put it into my model and send that model to QML. To achieve that I added to my gadget class a property of QList<QPoint> type that can be used on QML side. Sadly apparently it can only be used by a repeater at the Shape level and not into a shape to build it by using repeater on its children, but it's somehow a progress for me compared to my current implementation that uses a QAbstractListItem that builds shapes PathSvg.

                        SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote last edited by
                        #13

                        @Gilboonet I haven't got time to test it yet but something looks strange: why did you make the x and y methods private ?

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

                        GilboonetG 1 Reply Last reply
                        0
                        • SGaistS SGaist

                          @Gilboonet I haven't got time to test it yet but something looks strange: why did you make the x and y methods private ?

                          GilboonetG Offline
                          GilboonetG Offline
                          Gilboonet
                          wrote last edited by Gilboonet
                          #14

                          @SGaist It was generated using left click and refactor/add missing members of Q_PROPERTY, but I made them public and they are not reacheable on the QML side. I have the following error :

                          qt.qml.propertyCache.append: Final member x is overridden in class QQuickShape_QML_3. The override won't be used.
                          QQmlApplicationEngine failed to load component
                          qrc:/qt/qml/testQRange1/Main.qml:22:13: Cannot override FINAL property
                          

                          So I changed the names x and y to mx and my as there are already x and y on the shape class. But then it still doesn't work, same error saying required property was not initialized.

                          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
                          • Unsolved