QML Dynamic View Ordering Tutorial 4 - Sortieren von Objekten
Drag and Drop ist nicht der einzige Weg, wie Elemente in einer Ansicht neu geordnet werden können. Mit DelegateModel ist es auch möglich, Elemente basierend auf Modelldaten zu sortieren. Um dies zu tun, erweitern wir unsere DelegateModel Instanz wie folgt:
DelegateModel { id: visualModel property var lessThan: [ function(left, right) { return left.name < right.name }, function(left, right) { return left.type < right.type }, function(left, right) { return left.age < right.age }, function(left, right) { if (left.size == "Small") return true else if (right.size == "Small") return false else if (left.size == "Medium") return true else return false } ] property int sortOrder: orderSelector.selectedIndex onSortOrderChanged: items.setGroups(0, items.count, "unsorted") function insertPosition(lessThan, item) { let lower = 0 let upper = items.count while (lower < upper) { const middle = Math.floor(lower + (upper - lower) / 2) const result = lessThan(item.model, items.get(middle).model) if (result) { upper = middle } else { lower = middle + 1 } } return lower } function sort(lessThan) { while (unsortedItems.count > 0) { const item = unsortedItems.get(0) const index = insertPosition(lessThan, item) item.groups = "items" items.move(item.itemsIndex, index) } } items.includeByDefault: false groups: DelegateModelGroup { id: unsortedItems name: "unsorted" includeByDefault: true onChanged: { if (visualModel.sortOrder == visualModel.lessThan.length) setGroups(0, count, "items") else visualModel.sort(visualModel.lessThan[visualModel.sortOrder]) } } model: PetsModel {} delegate: dragDelegate }
Walkthrough
Elemente in einem DelegateModel werden in Gruppen gefiltert, die durch den Typ DelegateModelGroup repräsentiert werden. Normalerweise gehören alle Elemente im Modell zu einer Standardgruppe items, aber dieser Standard kann mit der Eigenschaft includeByDefault geändert werden. Um unsere Sortierung zu implementieren, möchten wir, dass die Elemente zunächst zu einer unsortierten Gruppe hinzugefügt werden, von wo aus wir sie in eine sortierte Position in der Elementgruppe übertragen können. Dazu löschen wir includeByDefault in der Gruppe items und setzen es auf eine neue Gruppe mit dem Namen "unsorted".
items.includeByDefault: false groups: DelegateModelGroup { id: unsortedItems name: "unsorted" includeByDefault: true }
Wir sortieren die Elemente, indem wir zuerst die Position in der Elementgruppe finden, an der das erste unsortierte Element eingefügt werden soll, und dann das Element in die Elementgruppe übertragen, bevor wir es an den vorher festgelegten Index verschieben und den Vorgang wiederholen, bis die unsortierte Gruppe leer ist.
Um die Einfügeposition für ein Element zu finden, fordern wir mit der Funktion get() ein Handle für das Element aus der unsortierten Gruppe an. Über die Modelleigenschaft dieses Handles können wir auf dieselben Modelldaten zugreifen, die in einer Delegateninstanz dieses Elements verfügbar sind, und sie mit anderen Elementen vergleichen, um die relative Position zu bestimmen.
function insertPosition(lessThan, item) { let lower = 0 let upper = items.count while (lower < upper) { const middle = Math.floor(lower + (upper - lower) / 2) const result = lessThan(item.model, items.get(middle).model) if (result) { upper = middle } else { lower = middle + 1 } } return lower } function sort(lessThan) { while (unsortedItems.count > 0) { const item = unsortedItems.get(0) const index = insertPosition(lessThan, item) item.groups = "items" items.move(item.itemsIndex, index) } }
Das lessThan-Argument der Sortierfunktion ist eine Vergleichsfunktion, mit der die Reihenfolge der Liste bestimmt wird. In diesem Beispiel kann es eine der folgenden sein:
property var lessThan: [ function(left, right) { return left.name < right.name }, function(left, right) { return left.type < right.type }, function(left, right) { return left.age < right.age }, function(left, right) { if (left.size == "Small") return true else if (right.size == "Small") return false else if (left.size == "Medium") return true else return false } ]
Eine Sortierung wird immer dann ausgelöst, wenn der unsortierten Liste DelegateModel neue Elemente hinzugefügt werden, worüber uns der DelegateModelGroup onChanged
Handler informiert. Wenn keine Sortierfunktion ausgewählt ist, übertragen wir einfach alle Elemente aus der unsortierten Gruppe in die Elementgruppe, andernfalls rufen wir sort mit der ausgewählten Sortierfunktion auf.
groups: DelegateModelGroup { id: unsortedItems name: "unsorted" includeByDefault: true onChanged: { if (visualModel.sortOrder == visualModel.lessThan.length) setGroups(0, count, "items") else visualModel.sort(visualModel.lessThan[visualModel.sortOrder]) } }
Wenn sich die gewählte Sortierreihenfolge ändert, können wir schließlich eine vollständige Neusortierung der Liste auslösen, indem wir alle Elemente aus der Elementgruppe in die unsortierte Gruppe verschieben, was den Handler DelegateModelGroup onChanged
auslöst und die Elemente in der richtigen Reihenfolge zurück in die Elementgruppe überträgt. Beachten Sie, dass der DelegateModelGroup onChanged
Handler nicht rekursiv aufgerufen wird, so dass es kein Problem gibt, wenn er während einer Sortierung aufgerufen wird.
property int sortOrder: orderSelector.selectedIndex onSortOrderChanged: items.setGroups(0, items.count, "unsorted")
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.