can anyone suggest how can we use
multiple delegates and multiple models in same list view in same qml?
can anyone suggest how can we use
multiple delegates and multiple models in same list view in same qml?
Can you give an example of what you intend to do?
A ListView works on a single model and single delegate at any given time, but of course either can be changed during runtime, etc.
Cheers,
_
Thanks for the reply.
My requirement is like i am getting different models from C++ side at runtime. Similarly i have to show these data in different kind of delegates in same qml.
Basically its a list screen which has different categories.
I tried to use loader for different delegates but i am not able to access the model from loader , however if i explicitly use one , one data from model as like variables i am able to do it , but model as a whole not able to.
I have even read that loader should be avoided .
Can you please suggest what kind of a design should i prefer for this
So any active model is replaced at some point by another?
Do you bind the ListView's model property to a C++ property that then gets changed?
Does the delegate change with the model or does the delegate need to display different things for any single model?
There are several options:
- you get the model data into local properties of the main delegate and then give the main delegate object to the loaded ite
- use Binding elements to bind the model data to the loaded item's properties
- make the ListView's delegate property an expression that evaluates to the wanted delegate instead of using a Loader
I am not aware of such a recommendation.
It really depends on your needs and I don't think I've understood them quite yet.
Cheers,
_
1.Yes active model is getting replaced by another model.Yes we are binding it to a c++ property.
2.Delegate changes for different model , different delegates are used.Some delegates, has to show only one information in field in list , some two , some more.
3.I tried the 3rd one , but whenever i am assigning from one delegate to another , it first goes and executes the first delegate and then the other one , hence i am getting reference errors, there is some context problem i think.I did not understand the first and 2nd option how to do it. If possible , please can you give a small code snippet for those 2 options.
4. I will search and let you know where i read , loader is not a good option.
5.I hope i can make you understand .
Thanks a lot for ur reply
So there is no direct association between model and delegate?
You need to switch delegate even if the model stays the same?
Base on some data in the model?
That sounds strange.
Can you give an example of how the binding for the delegate property looked in such a case?
In the first option you have some property in the item that gets loaded that is set to one of the object that always exist, e.g. the main delegate.
The loaded item always accesses that object's properties.
For the second option just look at the documentation of the Binding element: http://doc.qt.io/qt-5/qml-qtqml-binding.html
The target would be the Loader's "item", the property whatever it has and the value would be the "model" expression.
It is quite difficult to answer questions on such a highly abstract level, so any example would help.
Cheers,
_
Thank you very much for the reply.
So there is no direct association between model and delegate?
You need to switch delegate even if the model stays the same?
Base on some data in the model?
Yes there is direct association between model and delegate , for a specific model we have to show the details in a specific format.
So i have taken a specific delegate, for one model one delegate.Since we are getting the model from C++ and i see that this model contains data which is
not present in another models , so i have to make different delegates for different model , since my requirement is like that.
Can you give an example of how the binding for the delegate property looked in such a case?
Since my model is changing suppose the user has chosen some new categaory on a button press
Hence i am doing like
OnClicked{
mylistview.model=newmodel//the new model for the category
mylistview.delegate =newdelegate//the new way i have to show the data with new fields
}
Here in the above case i see when i assign like this it once again goes and executes the mylistview.delegate and then it goes to execute the newdelegate , hence in the previous case "mylistview.delegate" is executed and since the model is changed to the new model hence i get reference error.
In the first option you have some property in the item that gets loaded that is set to one of the object that always exist, e.g. the main delegate.
The loaded item always accesses that object's properties.
This wont be useful in my case as i have dynamic model
For the second option just look at the documentation of the Binding element: http://doc.qt.io/qt-5/qml-qtqml-binding.html
The target would be the Loader's "item", the property whatever it has and the value would be the "model" expression.
I already tried the above like below
Loader
{
........
property variant mymodel = model from C++
onLoaded:
Binding {
target: myloader.item
property: "mymodel "
value: mymodel
when: loader.status == Loader.Ready
}
}
but i see that the delegate is not able to access the data in this case.
however if i do something like this
inside loader
property var myalbumname = albumname //this is one role inside model
In the above case i am able to access the data in delegate but if iam trying to expose model as whole in loader i am not , i am not able to figure out where i am going wrong.
Ah, that should make it easier.
So there is a property that returns the current model.
Either on the same object or on each model have a property that returns some kind of identifier.
Then in QML, you use that identifier to switch between Components for the delegate
Qt Code:
ListView { model: cppObject.currentModel delegate: switch (cppObject.currentDelegate) { case "album": return albumDelegate; //.... } } Component { id: albumDelegate Text { text: model.albumname } }To copy to clipboard, switch view to plain text mode
I see.
Maybe first set the delegate to undefined, then change the model, then set the delegate to the new one
You don't want to access the model inside the delegate, but as usual the current index in the model, i.e. the data at for the current item.
But that doesn't help you anyway since your delegates all need different data.
Cheers,
_
Thanks for the reply.
I understand from your reply that now i have to switch between the components , but as i will be assigning from one previous to the new delegate , again i will get a reference error , just to verify what you suggested i have written a small example which contains 2 models and 2 delegates and i try to assign it alternatively , but as i am doing the first assignment of model and delegate in the first mouse click i get refernce error as usual
qml: entering assigning model
qrc:/main.qml:57: ReferenceError: name is not defined
qrc:/main.qml:57: ReferenceError: name is not defined
qrc:/main.qml:57: ReferenceError: name is not defined
qrc:/main.qml:64: ReferenceError: mylistview is not defined
qml: entering assigning modeln
Also below i am posting the code i wrote , please can you suggest how to get out of these errors.
Qt Code:
////////////////////////////////////////////////////// import QtQuick 2.3 import QtQuick.Window 2.2 Window { visible: true MouseArea { anchors.fill: parent onClicked: { console.log("entering assigning model") mylistview.model=model2 mylistview.delegate=comp2 } } ListModel{ id:model1 ListElement{ name:"Element1" } ListElement{ name:"Element2" } ListElement{ name:"Element3" } } ListModel{ id:model2 ListElement{ fame:"Element4" } ListElement{ fame:"Element5" } ListElement{ fame:"Element6" } } Component { id:comp1 Row{ Rectangle { width:50 height:50 color:"red" border.width: 2 border.color: "black" Text { text: name } MouseArea { anchors.fill: parent onClicked: { console.log("entering assigning model") mylistview.model=model2 mylistview.delegate=comp2 } } } } } Component { id:comp2 Row{ Rectangle { width:50 height:50 color:"blue" border.width: 2 border.color: "black" Text { text: fame } MouseArea { anchors.fill: parent onClicked: { console.log("entering assigning model") mylistview.delegate=comp1 mylistview.model=model1 } } } } } ListView { id:mylistview anchors.fill: parent model:model1 delegate: comp1 } } ////////////////////////////////////To copy to clipboard, switch view to plain text mode
Last edited by anda_skoa; 17th May 2016 at 22:42. Reason: missing [code] tags
Looks like you forgot the "assign undefined" part suggested above.
But then again, why worry about such a transient "error"
Cheers,
_
When i am trying to access the data of the second model from the mouse click , it is not happening , it cannot access the model data.
Can you also suggest how can i assign undefined to a delegate.
I tried something like this
mylistview.delegate = undefined
But this did not work out
Thank you for the reply
I tried the above suggestions but again the reference error issue , now the mylistview itself is not available.
Below is the whole code which i tried:
Qt Code:
import QtQuick 2.3 import QtQuick.Window 2.2 Window { visible: true Component{ id:emptycomp Item{} } ListModel{ id:model1 ListElement{ name:"Element1" } ListElement{ name:"Element2" } ListElement{ name:"Element3" } } ListModel{ id:model2 ListElement{ fame:"Element4" } ListElement{ fame:"Element5" } ListElement{ fame:"Element6" } } Component { id:comp1 Row{ Rectangle { width:50 height:50 color:"red" border.width: 2 border.color: "black" Text { text: name } MouseArea { anchors.fill: parent onClicked: { console.log("entering assigning model") mylistview.delegate=emptycomp mylistview.model=model2 mylistview.delegate=comp2 } } } } } Component { id:comp2 Row{ Rectangle { width:50 height:50 color:"blue" border.width: 2 border.color: "black" Text { text: fame } MouseArea { anchors.fill: parent onClicked: { console.log("entering assigning model") mylistview.delegate=emptycomp mylistview.delegate=comp1 mylistview.model=model1 } } } } } ListView { id:mylistview anchors.fill: parent model:model1 delegate: comp1 } }To copy to clipboard, switch view to plain text mode
Last edited by anda_skoa; 18th May 2016 at 15:44. Reason: missing [code] tags
Thank you fro all the support , the problem is solved
Bookmarks