我有一个QML应用程序,我正在创建从JavaScript接收的元素列表。使用this answer中的详细信息我将模型填充为JS数组,并且效果很好。但是,我喜欢它,以便当JavaScript对象的属性发生变化时,从它们驱动的ListView项目会更新。
这是一个显示问题的简单测试应用程序。 ListView
已正确填充显示正确ID /标题的MyRow
个实例,但当计时器更改rand
属性时,列行未更改(显示0
}为最后一项)。
MyRow.qml
import QtQuick 2.0
import QtQuick.Layouts 1.3
Rectangle {
property var obj
color:'#eeeeff'; height:20
RowLayout {
anchors.fill:parent
Text { text:obj.id }
Text { text:obj.title; Layout.fillWidth:true }
Text { text:obj.rand }
}
}
main.qml
import QtQuick 2.7
import QtQuick.Window 2.2
Window {
id:app; visible:true; width:200; height:100
property var database: ({"17":"World","42":"Hello"})
property var objById: ({})
function getObj(id){
if (!objById[id]) objById[id] = { id:id, title:database[id], rand:0 };
return objById[id];
}
ListView {
id:mylist
anchors.fill:parent
model: [42,17] // object ids
delegate: MyRow {
width:parent.width
obj:getObj(mylist.model[index])
}
}
Timer { // Update every object's rand value every second
interval:1000; running:true; repeat:true
onTriggered: {
Object.keys(objById).forEach(function(id){
objById[id].rand = Math.random()*100<<0;
})
}
}
}
当对象的属性发生变化时,如何让委托的Text
项更新文本?
答案 0 :(得分:1)
使属性绑定正常工作的最简单(唯一?)方法是创建真正的Qt对象来挂钩值。如果您不想使用ListModel
(因为您希望使用主库中的项快速填充模型),则可以使用createObject()
生成对象并将其传递给您的委托。
以下是根据需要运行的更新main.qml
:
Window {
// ...same as above...
Component { // Creates real Qt objects with bindable properties
id:objFactory
QtObject {
property int id
property string title
property int rand:0
}
}
function getObj(id){
if (!objById[id])
objById[id] = objFactory.createObject( app, {id:id,title:database[id]} );
return objById[id];
}
// ...same as above...
}
此外,您可能希望将property var obj
中的MyRow.qml
更改为更具体的property QtObject obj
(或更具体的对象类型,具体取决于您传入的内容)。
最后请注意,使用modelData
而不是mylist.model[index]
会更简洁/更简单:
ListView {
anchors.fill:parent
model: [42,17] // object ids
delegate: MyRow {
width:parent.width
obj:getObj(modelData)
}
}