Solved QVarianList in QVariantList flattening when passing into QML/JavaScript like Array in Array. Why?
-
Hello all!
I need to get array-in-array into Javascript from CPP. I am trying to get from QVarianList in QVariantList in CPP
QVariantList test::returnArray(void) { QVariantList vResult; QVariantList vValue; vValue.append(1); vValue.append("two"); vValue.append(true); vResult.insert(vResult.size(),vValue); vValue.append(2); vValue.append("two"); vValue.append(true); vResult.insert(vResult.size(),vValue); vValue.append(3); vValue.append("two"); vValue.append(true); vResult.insert(vResult.size(),vValue); return vResult; }
It's became flatten and duplicated. Result is:
qml: [1,two,true,1,two,true,2,two,true,1,two,true,2,two,true,3,two,true]
How to make something like this:
qml: [[1,"two",true],[2,"two",true],[3,"two",true]]
-
@bogong
I'm not sure, but have a look athttps://doc.qt.io/qt-5/qtqml-cppintegration-data.html, Sequence Type to JavaScript Array
https://doc-snapshots.qt.io/qt5-dev/qtqml-cppintegration-data.html, QVariantList and QVariantMap to JavaScript Array and Object
?
-
@JonB Thanks for reply. I've seen all of it. There are all OK when one-dimension array/QVarinatList. When I am trying to pass 2/3/4/n-dimensions array it's flattening. I need to avoid it.
-
@bogong
Yes, I do understand what you want, and that you're finding it gets flattened. The problem may be that it says things like QML supports, say,QList<int>
but notQList<QVariant>
. You might test with that to verify it is the (nested)QVariantList
which is the problem, it would work withQList<int>
instead? (You should of course verify back in C++ that your constructed list is indeed what we understand it to be, and not already flattened.)Trying to look for a workaround if you cannot solve/don't get a better answer, e.g. maybe https://doc.qt.io/qt-5/json.html would allow you to achieve it via JSON (https://stackoverflow.com/questions/41900383/parsing-json-in-qml)?
-
@JonB JSON - might be solution. But 2 additional conversion, from CPP to JSON-string and from JSON-string to JavaScript data. It might be very expensive for resources in case of big array.
-
I've tested:
- return like Q_PROPERTY(QJsonObject array READ array CONSTANT) in registered QML component
- return like registered object via QVarinatList
- return like registered object via QVariantMap
In every way it's flattening multi-dimensional arrays in one-dimensional.
The only way that I found is to create QString within JSON-String and parse it in QML JavaScript like JSON.parse(String). Look below on console log from pure CPP and QML:QJsonObject({"1":1,"2":2,"array":[[1,"2",true],[1,"2",true],[1,"2",true]]}) qml: [1,2,true,1,2,true,1,2,true]
But there are 2 additional senseless data conversions. In case of big portion of data in array (I've been testing it in 2000 elements and every element contain inner array of 17 element) this solution slowing down application hardly.
-
What about a
QJSValue
property type? -
@GrecKo What "what about"?
-
@GrecKo There are another trouble - architectural. The JS Engine should be one for whole application and It's starting from main:
int main(int Counter, char *Arguments[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication Application(Counter, Arguments); qmlRegisterType<CPPCustomQMLComponent>("Examples.cutomQMLComponent",1,0,"CustomComponent"); QQmlApplicationEngine Engine; Engine.load(QUrl(Main)); if (Engine.rootObjects().isEmpty()) return -1; return Application.exec(); }
For the case of dynamic usage it might be very complicated every time when I need simple multi-dimensional array to register it in global engine. I am trying to get it from non global object:
JSValue can't be reassigned to another engine. qrc:/main.qml:28: TypeError: Cannot read property 'array' of undefined
From:
QJSEngine oEngine; QJSValue vArray = oEngine.newArray(3); QJSValue vArrayInner = oEngine.newArray(3); vArrayInner.setProperty(0,1); vArrayInner.setProperty(1,"string"); vArrayInner.setProperty(2,true); vArray.setProperty(0,vArrayInner); vArray.setProperty(1,vArrayInner); vArray.setProperty(2,vArrayInner); return vArray;
-