Is there a way to make QML use 2D data model ?
-
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.
-
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.
-
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.
-
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-itemsYou should then be able to write
startY: model.y(with arequired property QtObject modelin the delegate) -
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-itemsYou should then be able to write
startY: model.y(with arequired property QtObject modelin the delegate)@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.
-
Can you share a minimal compilable application with your current code ?
That would allow us to check what is going on. -
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_Hmain.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)
-
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.
-
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.
@Gilboonet I haven't got time to test it yet but something looks strange: why did you make the
xandymethods private ? -
@Gilboonet I haven't got time to test it yet but something looks strange: why did you make the
xandymethods private ?@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 propertySo 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.