Solved QVector<CustomClass> as a var property in QML. Qt 5.14 vs 5.12.
-
Hello Ladies and Gentlemen.
Unsure if my idea would work, I created a DataPoint class marked with Q_GADGET with three properties defined using Q_PROPERTY. I placed Q_DECLARE_METATYPE(DataPoint) after the class definition. I also added qRegisterMetaType<DataPoint>() to the initialisation method of my main C++ class (let's call it MainClass).
In my MainClass I defined a property:
Q_PROPERTY(QVector<DataPoint> highPressureVector READ getHighPressureVector NOTIFY highPressureVectorChanged)
I fill a corresponding MainClass member (that is used in the getter) m_highPressureVector with three DataPoint objects.
In QML I use the forementioned property like this:
property var points: mainObject ? mainObject.highPressureVector : []
When I log its contents with:
console.log("points = " + points + ", points.length = " + points.length)
I get what I expect:
qml: points = DataPoint(0, 1, red),DataPoint(1,2,red),DataPoint(2,3,red), points.length = 3
The PROBLEM is that I did all this in Qt 5.14.2. I learned that we will use Qt 5.12.8. After compiling the exact same code with Qt 5.12.8 the line that prints points property looks like this:
qml: points = QVariant(QVector<DataPoint>), points.length = undefined
QUESTION: Is there a way to keep using QVector<DataPoint> as my property? Or do I have to make DataPoint inherit from QObject and use QVariantList or something like that?
I also have a second less important question. Why does this happen? I haven't seen anything in the Qt 5.14 version description that would justify such a difference in behaviour.
-
It seems that I'm not the only one who has encountered this problem:
https://stackoverflow.com/questions/58284209/how-to-pass-qvectorcustom-q-gadget-to-qmlThere is also a bug for that but it's still open even though QVector<GadgetClass> works in Qt 5.14.
https://bugreports.qt.io/browse/QTBUG-73399It seems that someone changed something in 5.14 that is not well documented but has made a significant change in handling QVectors of gadgets.
Since (for Qt 5.12) QML displays my points property as
QVariant(QVector<DataPoint>)
I assume that it is aware of the existence of DataPoint type. Why does it wrap it in QVariant in Qt 5.12? Is there a way to extract my vector from this variant so that QML treats it as an array?
-
OK, I gave up.
Instead of using Q_GADGET I made DataPoint class inherit from QObject and added Q_OBJECT macro to it. Then I turned my property which stores DataPoints into a QList:
Q_PROPERTY(QList<QObject*> highPressureList READ getHighPressureList NOTIFY highPressureListChanged)
I wish I could have kept QVector<GadgetClass> though...
I think that this is the change that is missing in 5.12 and is present in 5.14:
https://bugreports.qt.io/browse/QTBUG-60338 -
Does it make any different to register QVector<DataPoint> as well:
qRegisterMetaType<QVector<DataPoint>>()
-
I had some time to return to this problem and switch back DataPoint to Q_GADGET.
@fcarney said in QVector<CustomClass> as a var property in QML. Qt 5.14 vs 5.12.:
Does it make any different to register QVector<DataPoint> as well:
qRegisterMetaType<QVector<DataPoint>>()
Unfortunately it did not help. The vector in QML was visible as:
QVariant(QVector<DataPoint>)
-
I found a satisfying solution. When my DataPoint class is a Q_GADGET and is registered as a metatype:
Q_DECLARE_METATYPE(DataPoint);
qRegisterMetaType<DataPoint>();
it can be used in a QVariantList. The list is visible in QML as a JavaScript array. Then I can freely access all properties of each DataPoint in QML.
Adding an object of my DataPoint class to a QVariantList exposed to QML looks like this:
list.append(QVariant::fromValue(DataPoint{x, y, color}));
Reading a single DataPoint object from the QVariantList looks for example like this:
DataPoint lastdp = list.last().value<DataPoint>();