英文:
QML Repeater removes all delegate items and regenerates them again when model changes
问题
以下是您提供的文本的中文翻译:
通过更改模型(添加、删除或编辑模型的成员),重复器会移除所有已创建的项(代理),然后重新构建它们。对于大型模型来说,这是一个大问题。
我应该如何更改重复器,以便它不是移除所有代理,而是只删除与已删除成员相关的项,并在添加成员时仅创建与之相关的项,在编辑模型的成员时只删除并重新创建该成员。
我已经研究了与[Repeater](https://codebrowser.dev/qt5/qtdeclarative/src/quick/items/qquickrepeater.cpp.html#_ZN14QQuickRepeaterC1EP10QQuickItem)相关的代码,但由于其源代码中使用了私有方法和类,我无法重新实现它。
您可以使用下面的代码测试这个问题:
import QtQuick
import QtQuick.Controls
Window {
width: 640
height: 480
visible: true
title: qsTr("Ronia Components")
property var repeatreModel: [1, 2]
Timer {
interval: 2000
running: true
repeat: true
property int count: 0
onTriggered: {
count++;
// Add an item into model
repeatreModel.push(count);
}
}
Column {
anchors.fill: parent
Repeater {
id: repeater
model: repeatreModel
clip: true
onItemRemoved: (item, index) => {
console.log("Remove : (item, index) ", item, index)
}
onItemAdded: (item, index) => {
console.log("Add : (item, index) = ", item, index)
}
delegate: Rectangle {
width: 50
height: 40
Text {
id: name
anchors.centerIn: parent
text: modelData
}
}
onModelChanged: console.log("modelChanged")
}
}
}
请注意,这只是您提供的代码的中文翻译部分。如果您需要进一步的帮助或解释,请告诉我。
英文:
By changing the model (adding or subtracting or editing a member of the model), the repeater removes all the created items (delegates) and rebuilds them again. For heavy models, this is a big problem.
How can I change the repeater, so that instead of removing all delegates, it only deletes the item related to the deleted member, and when a member is added, it creates only the item related to it, and in case of editing a member of the model, only that member is removed and recreated.
I studied the code related to the Repeater, but due to the use of private methods and classes in its source, I cannot reimplement it.
You can test the problem with the bellow code:
import QtQuick
import QtQuick.Controls
Window {
width: 640
height: 480
visible: true
title: qsTr("Ronia Components")
property var repeatreModel: [1, 2]
Timer {
interval: 2000
running: true
repeat: true
property int count: 0
onTriggered: {
count++;
// Add an item into ,odel
repeatreModel.push(count);
}
}
Column {
anchors.fill: parent
Repeater {
id: repeater
model: repeatreModel
clip: true
onItemRemoved: (item, index) => {
console.log("Remove : (item, index) ", item, index)
}
onItemAdded: (item, index) => {
console.log("Add : (item, index) = ", item, index)
}
delegate: Rectangle {
width: 50
height: 40
Text {
id: name
anchors.centerIn: parent
text: modelData
}
}
onModelChanged: console.log("modelChanged")
}
}
}
答案1
得分: 0
不要为大型模型使用Repeater。更倾向于使用ListView或类似的项目(TreeView、TableView)。
引用自Qt的文档:
在使用Repeater时要考虑的事项
Repeater类型在创建时会同时创建所有的委托项目。如果有大量的委托项目,并且并非所有项目都需要同时可见,这可能会效率低下。如果情况如此,考虑使用其他视图类型,如ListView(仅在它们滚动到视图中时才创建委托项目),或者使用动态对象创建方法在需要时创建项目。
英文:
Don't use Repeater for large models.
Prefer ListView or similar items (TreeView, TableView).
Quote from Qt's documentation:
> Considerations when using Repeater
>
> The Repeater type creates all of its delegate items when the repeater
> is first created. This can be inefficient if there are a large number
> of delegate items and not all of the items are required to be visible
> at the same time. If this is the case, consider using other view types
> like ListView (which only creates delegate items when they are
> scrolled into view) or use the Dynamic Object Creation methods to
> create items as they are required.
答案2
得分: 0
SMR 说:
> Integer 和 JavaScript 数组模型是只读的 1。因此,您无法更新模型,任何更改都将重新创建所有实例。您应该使用 ListModel 代替。
基于此,我找到了一种可能的解决方案:
import QtQuick
import QtQuick.Controls
Window {
width: 640
height: 480
visible: true
title: qsTr("Ronia Components")
Timer {
interval: 2000
running: true
repeat: true
property int count: 0
onTriggered: {
count++;
listModel.append({"counter": count, "counter2": count*10})
}
}
ListModel {
id: listModel
}
Repeater {
id: repeater
model: listModel
clip: true
onItemRemoved: (item, index) => {
console.log("onItemRemoved: =", item, index)
}
onItemAdded: (item, index) => {
console.log("item, index =", item, index)
}
delegate: Rectangle {
x: counter + 2
y: counter2 + 20
width: 20
height: 20
Text {
id: name
anchors.centerIn: parent
text: counter2 + counter
}
}
onModelChanged: console.log("modelChanged")
}
}
注意:
我不想更改模型,因为我的模型在软件中被广泛使用,需要进行重大更改。
英文:
SMR said:
>Integer and JavaScript array models are read-only 1. Therefore, you cannot update the model, and any changes will recreate all of your instances. You should use ListModel instead.
Based on that, I figured out one of the possible solutions:
import QtQuick
import QtQuick.Controls
Window {
width: 640
height: 480
visible: true
title: qsTr("Ronia Components")
Timer {
interval: 2000
running: true
repeat: true
property int count: 0
onTriggered: {
count++;
listModel.append({"counter": count, "counter2": count*10})
}
}
ListModel {
id: listModel
}
Repeater {
id: repeater
model: listModel
clip: true
onItemRemoved: (item, index) => {
console.log("onItemRemoved: = ", item, index)
}
onItemAdded: (item, index) => {
console.log("item, index = ", item, index)
}
delegate: Rectangle {
x: counter + 2
y: counter2 + 20
width: 20
height: 20
Text {
id: name
anchors.centerIn: parent
text: counter2 + counter
}
}
onModelChanged: console.log("modelChanged")
}
}
Note:
I do not to want change the model, because my model is used a lot in the software, and needs drastic changes.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论