字符串数组模型更改时 ListView 不刷新
ListView does not refresh when string array model changes
添加新条目时,我的 ListView 不显示它们。
当对话框打开时,我将 QStringList 从 C++ 项目复制到 Qml 属性。
然后用户使用提供的控件修改数组(添加、修改、删除)。
遗憾的是,当我修改 属性 时,ListView 没有更新。 属性 已正确修改(如调试输出所示)。
如何使用数据绑定使 ListView 自动更新?
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
property var things
Component.onCompleted: things = [] // normally retrieved from C++ QStringList
ColumnLayout {
anchors.fill: parent
RowLayout {
Layout.fillWidth: true
TextField {
Layout.fillWidth: true
id: theTextField
}
Button {
Layout.fillWidth: true
text: qsTr("Append")
onPressed: {
things.push(theTextField.text)
console.log(things)
}
}
Button {
Layout.fillWidth: true
text: qsTr("Remove")
onPressed: {
var index = things.indexOf(theTextField.text)
if(index == -1)
console.warn('Not found!')
else
things.splice(index, 1)
console.log(things)
}
}
Button {
Layout.fillWidth: true
text: qsTr("Clear");
onPressed: {
things = [];
console.log(things)
}
}
}
ListView {
id: listView
Layout.fillWidth: true
Layout.fillHeight: true
model: things
delegate: Label {
text: modelData
}
}
}
}
原因是,使用函数修改things
时没有thingsChanged
信号。 things
中存储的引用将保持不变,无论您做什么。
对于 ListModel
这样的数据模型,这是相同的,但是存在 special signals 其中许多用于向任何视图指示它应该更新其内容。
如果您迫切需要使用数组,则需要手动调用 thingsChanged()
,每当您更改数组内容时。但这仅表示整个数组已更改,View
的主要优势之一是无效 - 仅更改已更改内容的能力。
当 View
对 thingsChanged
信号做出反应时,它会销毁所有当前委托,然后重新创建它们,无论是否有任何不同。
如果您使用 ListModel
或 QAbstractItemModel
-descendent,View
可以插入、删除或更改新委托的单个实例。
用真正的 ListModel 替换数组。使用函数追加!
Button {
Layout.fillWidth: true
text: qsTr("Clear");
onPressed: {
model.append({"data": theTextField.text})
}
}
and 在主块的 and 处
ListModel { id :model }
添加新条目时,我的 ListView 不显示它们。
当对话框打开时,我将 QStringList 从 C++ 项目复制到 Qml 属性。 然后用户使用提供的控件修改数组(添加、修改、删除)。
遗憾的是,当我修改 属性 时,ListView 没有更新。 属性 已正确修改(如调试输出所示)。
如何使用数据绑定使 ListView 自动更新?
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
property var things
Component.onCompleted: things = [] // normally retrieved from C++ QStringList
ColumnLayout {
anchors.fill: parent
RowLayout {
Layout.fillWidth: true
TextField {
Layout.fillWidth: true
id: theTextField
}
Button {
Layout.fillWidth: true
text: qsTr("Append")
onPressed: {
things.push(theTextField.text)
console.log(things)
}
}
Button {
Layout.fillWidth: true
text: qsTr("Remove")
onPressed: {
var index = things.indexOf(theTextField.text)
if(index == -1)
console.warn('Not found!')
else
things.splice(index, 1)
console.log(things)
}
}
Button {
Layout.fillWidth: true
text: qsTr("Clear");
onPressed: {
things = [];
console.log(things)
}
}
}
ListView {
id: listView
Layout.fillWidth: true
Layout.fillHeight: true
model: things
delegate: Label {
text: modelData
}
}
}
}
原因是,使用函数修改things
时没有thingsChanged
信号。 things
中存储的引用将保持不变,无论您做什么。
对于 ListModel
这样的数据模型,这是相同的,但是存在 special signals 其中许多用于向任何视图指示它应该更新其内容。
如果您迫切需要使用数组,则需要手动调用 thingsChanged()
,每当您更改数组内容时。但这仅表示整个数组已更改,View
的主要优势之一是无效 - 仅更改已更改内容的能力。
当 View
对 thingsChanged
信号做出反应时,它会销毁所有当前委托,然后重新创建它们,无论是否有任何不同。
如果您使用 ListModel
或 QAbstractItemModel
-descendent,View
可以插入、删除或更改新委托的单个实例。
用真正的 ListModel 替换数组。使用函数追加!
Button {
Layout.fillWidth: true
text: qsTr("Clear");
onPressed: {
model.append({"data": theTextField.text})
}
}
and 在主块的 and 处 ListModel { id :model }