Tutoriel QML sur l'ordonnancement dynamique des vues 4 - Tri des éléments
Le glisser-déposer n'est pas le seul moyen de réordonner les éléments d'une vue. En utilisant DelegateModel, il est également possible de trier les éléments en fonction des données du modèle. Pour ce faire, nous étendons notre instance DelegateModel comme suit :
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 }
Présentation
Les éléments d'un DelegateModel sont filtrés dans des groupes représentés par le type DelegateModelGroup. Normalement, tous les éléments du modèle appartiennent à un groupe items par défaut, mais cette valeur par défaut peut être modifiée à l'aide de la propriété includeByDefault. Pour mettre en œuvre notre tri, nous voulons que les éléments soient d'abord ajoutés à un groupe non trié à partir duquel nous pouvons les transférer à une position triée dans le groupe d'éléments. Pour ce faire, nous supprimons la propriété includeByDefault du groupe d'éléments et la définissons sur un nouveau groupe nommé "unsorted".
items.includeByDefault: false groups: DelegateModelGroup { id: unsortedItems name: "unsorted" includeByDefault: true }
Nous trions les éléments en trouvant d'abord la position dans le groupe d'éléments pour insérer le premier élément non trié, puis nous transférons l'élément dans le groupe d'éléments avant de le déplacer à l'index prédéterminé et nous répétons l'opération jusqu'à ce que le groupe d'éléments non triés soit vide.
Pour trouver la position d'insertion d'un élément, nous demandons une poignée pour l'élément du groupe non trié avec la fonction get(). Grâce à la propriété de modèle de cette poignée, nous pouvons accéder aux mêmes données de modèle que celles disponibles dans une instance de délégué de cet élément et les comparer à d'autres éléments pour déterminer la position relative.
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) } }
L'argument lessThan de la fonction de tri est une fonction de comparaison qui détermine l'ordre de la liste. Dans cet exemple, il peut s'agir de l'un des éléments suivants :
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 } ]
Un tri est déclenché chaque fois que de nouveaux éléments sont ajoutés à la liste non triée DelegateModel, ce dont nous sommes informés par le gestionnaire DelegateModelGroup onChanged . Si aucune fonction de tri n'est actuellement sélectionnée, nous transférons simplement tous les éléments du groupe non trié vers le groupe d'éléments, sinon nous appelons le tri avec la fonction de tri sélectionnée.
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]) } }
Enfin, lorsque l'ordre de tri sélectionné change, nous pouvons déclencher un nouveau tri complet de la liste en déplaçant tous les éléments du groupe d'éléments vers le groupe non trié, ce qui déclenchera le gestionnaire DelegateModelGroup onChanged et transférera à nouveau les éléments dans le groupe d'éléments dans l'ordre correct. Notez que le gestionnaire DelegateModelGroup onChanged ne sera pas invoqué de manière récursive, il n'y a donc aucun problème à ce qu'il soit invoqué pendant un tri.
property int sortOrder: orderSelector.selectedIndex onSortOrderChanged: items.setGroups(0, items.count, "unsorted")
© 2026 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.