Using a js-list, understanding qml lists?
-
Hi, i have a javascript-function that returns a list of strings. I want to to use each string in a separate qml label. I don't want to run the javascript-function more than once.
I've been trying to understand lists in qml to try and transfer the list in some way, but i'm not sure if i'm even going in the right direction.
Thanks for any help.
-
@
Label {
text: myJsList[0]
}
@Or, from a function, since you want to run it once only (assuming that all "labels" are children of an item with id "container"):
@
function applyTextToLabels() {
for (var i = 0; i < myJsList.length; i++) {
container.children[i].text = myJsList[i];
}
}
@Is that more or less what you want to achieve or did I misunderstand?
-
Well if i could just create my labels like your first example it'd be lovely, but what i don't understand is how to make a myJsList like that available to the qml parts. I experimented a bit with using js inside qml (like "http://doc.qt.nokia.com/latest/qdeclarativejavascript.html":http://doc.qt.nokia.com/latest/qdeclarativejavascript.html) but can't get it to work. I did it like this now as preparation, trying to find a way to make the call only once in the first part.
@ Item {
id: generatedTexts
children: [
Text { id: text1; text: GenerateScript.generateFunction()[0]; visible: false },
Text { id: text2; text: GenerateScript.generateFunction()[1]; visible: false },
Text { id: text3; text: GenerateScript.generateFunction()[2]; visible: false }
]
}Text { id: label1 text: generatedTexts.children[0].text }
etc...@
-
OK I think I am slowly getting the idea of what you need. Let's prod the matter a bit further.
The generateFunction() seems to be returning a JS array. You want to run it once only. There are several solutions I can think of. Let's try the first one, if it does not satisfy you, we'll try some more :) What I would suggest is storing the resulting array. You would run the function once to get the array, and then just use it for your text items. If you prefer storing it in JS file, just add this to the script:
@
var myArray = new Array();
@And then assign the value somewhere in your code. From your QML, just call:
@
Text {
id: label1
text: GenerateScript.myArray[0];
}
@If that is not enough, you can store whole QML objects in an array. If you want - as I guess you do - store the list on the QML side, it's also possible, with "variant" and "list<>" properties. I would write a bit more, but am in a hurry. Will come back later.
-
I don't really understand that one, populate and access an array in the js-file i get but i still have to call the js function one time right, and i don't think i can just put js-calls without context in the qml-file?
I did manage to store it in the js-file like this, calling the new function from qml instead:
@var generatedList;
var listGeneratedBool = false;function getList(){
if (!(listGeneratedBool)) {
generatedList = generateFunction();
listGeneratedBool = true;
}
return generatedList;
}@But like you rightly say i'm interested in storing on the qml-side, I'll have a closer look at those properties you mentioned and see what i can understand...
-
OK, a bit more time now.
I had some tough experiences with variant and list<> properties, that's why I've started with the JS trick. Try variant first, it's easier to get it working. For example:
@
// In your root item, or else.
property variant myList;// This will run once, on init, and assign the array to the property.
Component.onCompleted {
myList = GenerateScript.generateFunction();
}
@
I won't guarantee it will work, as I've mentioned, those properties are a bit harder to work with. You'll have to experiment. Especially list<> can be a pain if you have a dynamic list of objects.I still don't know how exactly are you generating those texts, but I'll briefly mention another 2 possibilities you may want to explore:
- QML-C++ bindings, which allow you to store lists in C++, where you're got total control over them
- generating JS list of QML Components. Here's a nice "link":http://developer.qt.nokia.com/doc/qt-4.8/qml-qt.html#id-8009f2be-7f41-4ad9-b8bc-647ee477e854. I've used this technique a few times, works nicely with both JS Array()s, and variant and list<> properties.
-
You could use your javascript string array as a source for filling up a Qml ListModel.
Then use that as the model for a Repeater. Would that work for you?
@
Item {ListModel { id: myModel }
Repeater {
model: myModel
delegate: Text { /* ... */ }
}function rebuildModel() {
var stringArray = buildStringArray(); // your javascript method
myModel.clear()
for (var i = 0; i < stringArray.length; ++i) {
myModel.append( { "text": stringArray[i] } )
}
}Component.onCompleted: rebuildModel()
}
@