Reputation: 2613
I'm having a problem with a ListView
and a simple ListModel
;
import QtQuick 2.12
import QtQuick.Controls 2.12
ApplicationWindow
{
id: app
visible: true
width: 640
height: 480
property int bheight: 48
ListModel
{
id: jmodel
}
function dosomething1()
{
jmodel.clear();
jmodel.append({"atext":"hello"})
}
function dosomething2()
{
jmodel.clear();
jmodel.append({"atext":"hello","btext":"world"});
}
ListView
{
id: alist
width: parent.width
height: parent.height - bheight
model: jmodel
delegate: Item
{
width: app.width
height: 48
Row
{
spacing: 8
Text
{
text: model.atext || ""
}
Text
{
text: model.btext || ""
}
}
}
}
Row
{
height: bheight
anchors.top: alist.bottom
Button
{
// press "plan A" first and it will say "hello"
// press "plan B" after and it will remain "hello"
// pressing A & B will NOT toggle
text: "Plan A"
onClicked: dosomething1();
}
Button
{
// press "plan B" first and it will say "hello world"
// press "plan A" after and it will say "hello"
// pressing A & B will toggle
text: "Plan B"
onClicked: dosomething2();
}
}
}
I can't get it to work consistently. Maybe there's something simple missing or i do not understand.
Pressing "Plan A" will say "hello" and after pressing "Plan B" will not change it.
But,
Pressing "Plan B" first will say "hello world", and thereafter pressing "plan A" and "plan B" will toggle between "hello world" and "hello".
It should not depend on what button is pressed first, i am clearing the model each time.
I have tried this on Qt5.12.3 and 5.9 and there is no change.
Following @eyllanesc answer, i've updated my code to instead create a new model for each update. This works but i don't know if i now have a memory leak.
this is my code:
import QtQuick 2.12
import QtQuick.Controls 2.12
ApplicationWindow
{
id: app
visible: true
width: 640
height: 480
property int bheight: 48
Component
{
id: jmodel
ListModel {}
}
function dosomething1()
{
var m = jmodel.createObject()
m.append({"atext":"hello"})
alist.model = m;
}
function dosomething2()
{
var m = jmodel.createObject()
m.append({"atext":"hello","btext":"world"});
alist.model = m;
}
ListView
{
id: alist
width: parent.width
height: parent.height - bheight
delegate: Item
{
width: app.width
height: 48
Row
{
spacing: 8
Text
{
text: model.atext || ""
}
Text
{
text: model.btext || ""
}
}
}
}
Row
{
height: bheight
anchors.top: alist.bottom
Button
{
text: "Plan A"
onClicked: dosomething1();
}
Button
{
text: "Plan B"
onClicked: dosomething2();
}
}
}
Upvotes: 1
Views: 116
Reputation: 244282
As the docs point out:
Modifying List Models
Modifying List Models The content of a ListModel may be created and modified using the clear(), append(), set(), insert() and setProperty() methods. For example:Component { id: fruitDelegate Item { width: 200; height: 50 Text { text: name } Text { text: '$' + cost; anchors.right: parent.right } // Double the price when clicked. MouseArea { anchors.fill: parent onClicked: fruitModel.setProperty(index, "cost", cost * 2) } } }
Note that when creating content dynamically the set of available properties cannot be changed once set. Whatever properties are first added to the model are the only permitted properties in the model.
(emphasis added)
You can not add or remove the properties after initially establishing them:
In case 1 your model only has the atext property initially, and then you want to add the btext property but Qt does not allow it.
In case 2 your model has the properties atext and btext, then you just rewrite the atext property so btext still exists and will have a value of null.
The solution in this case is to set btext with a default value in case 1:
function dosomething1()
{
jmodel.clear();
jmodel.append({"atext":"hello", "btext":""}) // <----
}
Upvotes: 0