Can't get values from QList in QML
-
Hello!
I have my simple class that should give access to QList:struct ChartPoint { int x; int y; }; class ChartPointList : public QObject { Q_OBJECT Q_PROPERTY(QList<ChartPoint> list READ chartPointList /*WRITE setChartPointList*/ NOTIFY chartPointListChanged) public: ChartPointList(QObject* parent) : QObject(parent) { /* for test */ m_chartPointList.append(ChartPoint{1, 1}); } QList<ChartPoint> chartPointList() const; signals: void chartPointListChanged(); private: QList<ChartPoint> m_chartPointList; };
I registered type in
main.cpp
:qmlRegisterType<ChartPointList>("com.myinc.ChartPointList", 1, 0, "ChartPointList");
but I can't get values from the list.
console.log(first.list); console.log(first[0].x);
show
qml: QVariant(QList<ChartPoint>, ) qrc:/QML-graph/Main.qml:20: TypeError: Cannot read property 'x' of undefined
Perhaps I should use QVariant in some way?
Or maybe the whole approach is wrong...My goal is to read a file with c++ and make a list of points (x, y) from it. And then via ChartView draw these points on the chart.
Thanks for any tips!
-
Hello!
I have my simple class that should give access to QList:struct ChartPoint { int x; int y; }; class ChartPointList : public QObject { Q_OBJECT Q_PROPERTY(QList<ChartPoint> list READ chartPointList /*WRITE setChartPointList*/ NOTIFY chartPointListChanged) public: ChartPointList(QObject* parent) : QObject(parent) { /* for test */ m_chartPointList.append(ChartPoint{1, 1}); } QList<ChartPoint> chartPointList() const; signals: void chartPointListChanged(); private: QList<ChartPoint> m_chartPointList; };
I registered type in
main.cpp
:qmlRegisterType<ChartPointList>("com.myinc.ChartPointList", 1, 0, "ChartPointList");
but I can't get values from the list.
console.log(first.list); console.log(first[0].x);
show
qml: QVariant(QList<ChartPoint>, ) qrc:/QML-graph/Main.qml:20: TypeError: Cannot read property 'x' of undefined
Perhaps I should use QVariant in some way?
Or maybe the whole approach is wrong...My goal is to read a file with c++ and make a list of points (x, y) from it. And then via ChartView draw these points on the chart.
Thanks for any tips!
@Atr0p0syou in your case, you
need toshould work with QProperties, if you want to access the data from QML:class ChartPoint { Q_GADGET Q_PROPERTY(int x MEMBER m_x) Q_PROPERTY(int y MEMBER m_y) public: int m_x; int m_y; };
-
@Atr0p0syou in your case, you
need toshould work with QProperties, if you want to access the data from QML:class ChartPoint { Q_GADGET Q_PROPERTY(int x MEMBER m_x) Q_PROPERTY(int y MEMBER m_y) public: int m_x; int m_y; };
@J-Hilk Thanks, the list is now recognizable as I can see, but the point isn't:
console.log(first.list); --- qml: [ChartPoint(1, 1)] console.log(first[0]); --- qml: undefined console.log(first[0].x); --- Cannot read property 'x' of undefined
Header:
class ChartPoint { Q_GADGET Q_PROPERTY(int x MEMBER m_x) Q_PROPERTY(int y MEMBER m_y) public: int m_x; int m_y; }; class ChartPointList : public QObject { Q_OBJECT Q_PROPERTY(QList<ChartPoint> list READ chartPointList NOTIFY chartPointListChanged) QML_ELEMENT public: ChartPointList(QObject* parent = nullptr); QList<ChartPoint> chartPointList() const; signals: void chartPointListChanged(); private: QList<ChartPoint> m_chartPointList; };
I registered both classes:
qmlRegisterType<ChartPoint>("com.myinc.chartPoint", 1, 0, "ChartPoint"); qmlRegisterType<ChartPointList>("com.myinc.chartPointList", 1, 0, "ChartPointList");
Also, I get the warning in the output:
qt.qml.typeregistration: Invalid QML element name "ChartPoint"; value type names should begin with a lowercase letter
, but if I writechartPoint
instead ofChartPoint
then instead of this warning I get a new one in IDE:QML types must begin with uppercase.
Of course, I could use special functions to get x and y values such as
int ChartPointList::valueX(int index) const { return m_chartPointList.value(index).m_x; }
but I wish it was a little prettier.
-
@J-Hilk Thanks, the list is now recognizable as I can see, but the point isn't:
console.log(first.list); --- qml: [ChartPoint(1, 1)] console.log(first[0]); --- qml: undefined console.log(first[0].x); --- Cannot read property 'x' of undefined
Header:
class ChartPoint { Q_GADGET Q_PROPERTY(int x MEMBER m_x) Q_PROPERTY(int y MEMBER m_y) public: int m_x; int m_y; }; class ChartPointList : public QObject { Q_OBJECT Q_PROPERTY(QList<ChartPoint> list READ chartPointList NOTIFY chartPointListChanged) QML_ELEMENT public: ChartPointList(QObject* parent = nullptr); QList<ChartPoint> chartPointList() const; signals: void chartPointListChanged(); private: QList<ChartPoint> m_chartPointList; };
I registered both classes:
qmlRegisterType<ChartPoint>("com.myinc.chartPoint", 1, 0, "ChartPoint"); qmlRegisterType<ChartPointList>("com.myinc.chartPointList", 1, 0, "ChartPointList");
Also, I get the warning in the output:
qt.qml.typeregistration: Invalid QML element name "ChartPoint"; value type names should begin with a lowercase letter
, but if I writechartPoint
instead ofChartPoint
then instead of this warning I get a new one in IDE:QML types must begin with uppercase.
Of course, I could use special functions to get x and y values such as
int ChartPointList::valueX(int index) const { return m_chartPointList.value(index).m_x; }
but I wish it was a little prettier.
-
@Atr0p0s It's possible that QGadget is not enough, I thought it is but I may be wrong. Make it a proper QObject and use the
Q_OBJECT
macro instead@J-Hilk Still doesn't work. Perhaps I should use a model or functions for direct access to the data?
What I tried:
//thing-object.h class Thing : public QObject { Q_OBJECT Q_PROPERTY (int size READ getSize CONSTANT) Q_PROPERTY (QString name READ getName CONSTANT) public: Thing(QObject * parent = NULL) : QObject(parent) {} int getSize () const { return m_size; } void setSize (int s) { m_size = s; } QString getName () const { return m_name; } void setName (QString n) { m_name = n; } private: int m_size; QString m_name; }; class ThingManager : public QObject { Q_OBJECT Q_PROPERTY(QList<Thing*> things READ getThings NOTIFY thingsChanged) public: QList<Thing*> getThings () const { return m_things; } void append (Thing* thg) { m_things.append(thg); } signals: void thingsChanged (); private: QList<Thing*> m_things; }; //main.cpp #include "thing-object.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); qmlRegisterType<Thing>("com.myinc.thing", 1, 0, "Thing"); qmlRegisterType<ThingManager>("com.myinc.thingManager", 1, 0, "ThingManager"); Thing* thg = new Thing; thg->setSize(5); thg->setName("Cow"); ThingManager man; man.append(thg); QQmlApplicationEngine engine; engine.rootContext()->setContextProperty(QStringLiteral("first"), &man); const QUrl url(u"qrc:/testAgain/Main.qml"_qs); QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); } //main.qml import QtQuick import QtQuick.Window import com.myinc.thing import com.myinc.thingManager import QtQuick.Controls Window { width: 640 height: 480 visible: true title: qsTr("Hello World") Button { text: "Press" onClicked: { console.log(first.things); console.log(first[0].size); } } }
-
@J-Hilk Still doesn't work. Perhaps I should use a model or functions for direct access to the data?
What I tried:
//thing-object.h class Thing : public QObject { Q_OBJECT Q_PROPERTY (int size READ getSize CONSTANT) Q_PROPERTY (QString name READ getName CONSTANT) public: Thing(QObject * parent = NULL) : QObject(parent) {} int getSize () const { return m_size; } void setSize (int s) { m_size = s; } QString getName () const { return m_name; } void setName (QString n) { m_name = n; } private: int m_size; QString m_name; }; class ThingManager : public QObject { Q_OBJECT Q_PROPERTY(QList<Thing*> things READ getThings NOTIFY thingsChanged) public: QList<Thing*> getThings () const { return m_things; } void append (Thing* thg) { m_things.append(thg); } signals: void thingsChanged (); private: QList<Thing*> m_things; }; //main.cpp #include "thing-object.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); qmlRegisterType<Thing>("com.myinc.thing", 1, 0, "Thing"); qmlRegisterType<ThingManager>("com.myinc.thingManager", 1, 0, "ThingManager"); Thing* thg = new Thing; thg->setSize(5); thg->setName("Cow"); ThingManager man; man.append(thg); QQmlApplicationEngine engine; engine.rootContext()->setContextProperty(QStringLiteral("first"), &man); const QUrl url(u"qrc:/testAgain/Main.qml"_qs); QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); } //main.qml import QtQuick import QtQuick.Window import com.myinc.thing import com.myinc.thingManager import QtQuick.Controls Window { width: 640 height: 480 visible: true title: qsTr("Hello World") Button { text: "Press" onClicked: { console.log(first.things); console.log(first[0].size); } } }
@Atr0p0s said in Can't get values from QList in QML:
console.log(first[0].size);
shouldn't this be
first.things[0].size
? -
@Atr0p0s said in Can't get values from QList in QML:
console.log(first[0].size);
shouldn't this be
first.things[0].size
? -
A Atr0p0s has marked this topic as solved on
-
@J-Hilk I am so sorry, keep forgetting that there is no compile time error checking :(
You are right - it works also with Q_GADGET.
Thanks a lot!Could you also advise please, if qml copies the entire list to access one element?
@Atr0p0s said in Can't get values from QList in QML:
I am so sorry, keep forgetting that there is no compile time error checking :(
You are right - it works also with Q_GADGET.Don't worry a pit fall I myself fall into regularly :D
Could you also advise please, if qml copies the entire list to access one element?
That I'm unsure about, sorry. I know that QObjects can't be copied, and its also kind of irrelevant, as its a list of pointers :D
Just make sure to handle ownership of the objects correctly or the QML will take ownership and may GC them at any moment it sees fit.
-
@Atr0p0s said in Can't get values from QList in QML:
I am so sorry, keep forgetting that there is no compile time error checking :(
You are right - it works also with Q_GADGET.Don't worry a pit fall I myself fall into regularly :D
Could you also advise please, if qml copies the entire list to access one element?
That I'm unsure about, sorry. I know that QObjects can't be copied, and its also kind of irrelevant, as its a list of pointers :D
Just make sure to handle ownership of the objects correctly or the QML will take ownership and may GC them at any moment it sees fit.