List of lists refreshing error
-
Hello friends!
I've got some problem in QML. I made a list of lists with ListView. The main list's model is ObjectModel. SubList's model is ListModel with horizontalView. Both of them are populated dynamically. The problem is that, when I clear my ObjectModel and reappend those objects(refresh the list) again, it clears, but crashes with somehow problem. Here is my code:
//--------Main list's ObjectModel--------
ObjectModel{id: groups Component{ id: groupItem Item { height: 280 width: lvGroups.width clip: true property string groupName: "New" // Caption of the group Text { id: groupCaption anchors { topMargin: 8 leftMargin: 32 } font.pointSize: txtSize+6 text: '<b>'+groupName+'</b>' } ListModel { id: itemList // ListElement { //subList's Item structure // name: "product" // cost: "12500.00" // icon: "file://" // group: "grp_0" // } } function addItem(nm, cs, grp, icn) // function to add item for subList's model { itemList.append({'name': nm, 'cost': cs, 'group': grp, 'icon': icn}) } //function clearItems() { itemList.clear() } ListView{ // subList with horizontalView width: parent.width anchors { bottom: groupItem.bottom top: groupCaption.bottom } orientation: ListView.Horizontal spacing: 8 boundsBehavior: Flickable.StopAtBounds model: itemList delegate: Item{ width: 180 height: parent.height-16 anchors.verticalCenter: parent.verticalCenter Image { id: itemIcon anchors.horizontalCenter: parent.horizontalCenter width: 120 height: 120 source: icon!='' ? icon : "res/image.png" } Text{ id: nametxt text: name anchors{ top: itemIcon.bottom topMargin: 8 horizontalCenter: parent.horizontalCenter } font.pointSize: txtSize elide: Text.ElideRight Component.onCompleted: if (width>parent.width-16) width=parent.width-16 } Text{ text: cost anchors{ top: nametxt.bottom topMargin: 4 horizontalCenter: parent.horizontalCenter } font.pointSize: txtSize Component.onCompleted: if (width>parent.width-16) width=parent.width-16 } MouseArea{ anchors.fill: parent onClicked: { addToBacket(name, cost) } //it's a function outside that adds to another list } } } } } }
//--------Main ListView--------
ListView {id: lvGroups anchors { top: backet.bottom bottom: bottomBar.top right: parent.right left: parent.left leftMargin: 16 rightMargin: 16 } boundsBehavior: Flickable.StopAtBounds clip: true spacing: 32 model: groups } // it doesn't need delegate, coz the model is ObjectModel (as told in Documentation)
//--------Function to clear the mainList--------
function clearList() { groups.clear() } // it's called from Main.qml//--------MenuItmInf is a custom property assigned to C++ code--------
onMenuItmInfChanged: {if (menuItmInf=="") return var nm = menuItmInf.substring(0, menuItmInf.indexOf('*')); var cs = menuItmInf.substring(menuItmInf.indexOf('*')+1, menuItmInf.indexOf('~')) var gr = menuItmInf.substring(menuItmInf.indexOf('~')+1, menuItmInf.indexOf('#')) var ic = menuItmInf.substring(menuItmInf.indexOf('#')+1, menuItmInf.length) for (var i=0; i<lvGroups.count; i++)
// if (groups.get(i)===null) continue
// elseif (groups.get(i).groupName === gr) { groups.get(i).addItem(nm,cs,gr,ic) return } groups.append(groupItem.createObject()) // create a new group into Group's list (main list) groups.get(lvGroups.count-1).groupName = gr groups.get(lvGroups.count-1).addItem(nm,cs,gr,ic) }
Here is the screenshot: https://ibb.co/Sc2xb1KFinally: After refreshing the list (i.e. clearing and reappending items) i'm getting this error:
W libBTClient.so: qrc:/Itemslist.qml:306: TypeError: Cannot read property 'groupName' of null
-
I think I have found the solution)) from this link.
https://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.html
and this link also helped me to understand the error:
https://stackoverflow.com/questions/45387244/how-to-remove-a-dynamically-created-item-from-column-qml-element
There was said:
you should never rely on the garbage collector. It will only work relieably when you use component.createObject(null) and then it will relieably destroy your object at random times, most likely before you want it to be gone, as the reference counting is broken. If it runs to seldomly your application will crash as soon as it runs. If you use component.createObject(someParent) it won't work at all.Creating a Component Dynamically
To dynamically load a component defined in a QML file, call the Qt.createComponent() function in the Qt object. This function takes the URL of the QML file as its only argument and creates a Component object from this URL.Once you have a Component, you can call its createObject() method to create an instance of the component. This function can take one or two arguments:
->The first is the parent for the new object. The parent can be a graphical object (i.e. of the Item type) or non-graphical object (i.e. of the QtObject or C++ QObject type). Only graphical objects with graphical parent objects will be rendered to the Qt Quick visual canvas. If you wish to set the parent later you can safely pass null to this function.
->The second is optional and is a map of property-value ...So, my mistake was at creating the group's ItemObject without parent. So I fixed that line as this:
groups.append(groupItem.createObject(lvGroups)) // create a new group into Group's list (main list)