Solved Help with model for repeater
-
Hi,
I am trying to make a QML component for drawing x vs y plots. I am drawing the ticks and labels using a repeater in QML:
Item { anchors.fill: parent visible: true Repeater { model:canvas.xTickPos.length Rectangle{ height: 4 width: 2 x: canvas.xTickPos[index] y: parent.height-height visible: true color: "black" border.width: 2 } } }
Right now, as a model I am using a javascript array which is a property in the qml file. However, I would like to move the model to the c++ side, and I guess I should do it with a QStandardItemModel or a QAbstractItemModel. The model should contain two variables: tick position (a double) and label (a string). How would you write such a model?
-
Here is a minimal example:
myitemmodel.h
#ifndef MYITEMMODEL_H #define MYITEMMODEL_H #include <QAbstractListModel> struct MyItem{ double tickPos; QString label; }; class MyItemModel : public QAbstractListModel { Q_OBJECT enum roles{ ROLE_TICK_POS = Qt::UserRole + 1, ROLE_LABEL, }; public: MyItemModel(QObject *parent = nullptr); // Basic functionality: int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; virtual QHash<int,QByteArray> roleNames() const; QList<MyItem> items() const; void setItems(const QList<MyItem> &items); private: QList<MyItem> m_items; }; #endif // MyItemModel_H
myitemmodel.cpp
#include "MyItemmodel.h" MyItemModel::MyItemModel(QObject *parent) : QAbstractListModel(parent) { } int MyItemModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; return m_items.count(); } QVariant MyItemModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() >= m_items.count()) return QVariant(); MyItem i = m_items.at(index.row()); switch(role){ case ROLE_TICK_POS: return i.tickPos; case ROLE_LABEL: return i.label; } return QVariant(); } QHash<int, QByteArray> MyItemModel::roleNames() const { QHash<int, QByteArray> roles; roles[ROLE_TICK_POS] = "role_tickPos"; roles[ROLE_LABEL] = "role_label"; return roles; } QList<MyItem> MyItemModel::items() const { return m_items; } void MyItemModel::setItems(const QList<MyItem> &items) { beginResetModel(); m_items = items; endResetModel(); }
main.cpp:
MyItemModel myModel; myModel.setItems(...); QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("myModel", &myModel);
Then in QML:
Repeater { model: myModel Rectangle{ height: 4 width: 2 x: role_tickPos //Use role_label to access label value of the current item y: parent.height-height visible: true color: "black" border.width: 2 } }
- I didn't compile it so it mays have some errors in the code.
- As I said this is the minimal example but you can then add more features to the model if you need it.
- Note that the model can also be a property of a QObject instances set as context property in QML engine.
-
Thank you very much!