我在使用我指定的字段中的值對QListView
中的項目進行排序時遇到了一些問題。如何使用Qt.UserRole對Qt QListview中的項目進行排序
基本上我想要做的是這樣的:
- 檢測人臉的照片集並在
QListView
- 集羣顯示他們的面孔(圖片)
- 更新視圖通過將屬於同一羣集的列表中的項目(它們是面部圖像)放在一起。具體地說,如果項目1,3,5在一個集羣中並且項目2,4,6在另一個集羣中,那麼在顯示項目2,4,6中的任何一個之前應該顯示項目1,3,5(以任意排列方式)或相反亦然。
我去這樣做的方法就是在我的名單到集羣標籤設置UserRole
領域之一每個QStandardItem
,然後試圖讓QStandardModel
根據本UserRole
排序。然後這會將項目顯示在彼此相鄰的同一個羣集中(即在UserRole
中具有相同的羣集標籤)。
我能夠設置UserRole
成功的項目,但呼籲QStandardModel
排序功能的項目,即使當我設置樣的角色成爲默認DisplayRole
(沒有進行排序,即排序根據文本標籤每面的)它按預期工作。
任何人都可以告訴我什麼是我的代碼錯誤或提供一種替代方法?我已經使用了排序列表,我在QSortFilterProxyModel上找到了以下鏈接,但由於我對Qt相當陌生,因此無法適應我的情況。
在此先感謝您的答覆。
下面是相關代碼:
import os
from PySide.QtGui import QListView, QStandardItemModel, QStandardItem, QIcon
from PySide.QtCore import Qt
class FacesView(QListView):
"""
View to display detected faces for user to see and label.
"""
UNCLUSTERED_LABEL = -1
CLUSTER_ROLE = Qt.UserRole + 1
def __init__(self, *args):
super(FacesView, self).__init__(*args)
self._dataModel = QStandardItemModel()
self.setModel(self._dataModel)
# Layout items in batches instead of waiting for all items to be
# loaded before user is allowed to interact with them.
self.setLayoutMode(QListView.Batched)
def updateFaceClusters(self, labels):
"""Update the cluster label for each face.
@param labels: [1 x N] array where each element is an integer
for the cluster the face belongs to."""
assert(len(labels) == self._dataModel.rowCount())
# Put the cluster label each item/face belong to in the
# CLUSTER_ROLE field.
for i in xrange(self._dataModel.rowCount()):
index = self._dataModel.index(i, 0)
self._dataModel.setData(index, labels[i], self.CLUSTER_ROLE)
# Use cluster label as sort role
self._dataModel.setSortRole(self.CLUSTER_ROLE)
# This does NOT seem to sort the items even though it works fine
# when sort role is the default Qt.DisplayRole.
self._dataModel.sort(0)
print("Finished updating face clusters")
def itemsInList(self):
"""Returns the label for a face and the path to its image.
@return: (label, path)"""
items = []
for i in xrange(self._dataModel.rowCount()):
label = self._dataModel.index(i, 0).data(Qt.DisplayRole)
imagePath = self._dataModel.index(i, 0).data(Qt.UserRole)
clusterLabel = self._dataModel.index(i, 0).data(self.CLUSTER_ROLE)
items.append((imagePath, label, clusterLabel))
return items
def addItem(self, label, imagePath):
"""Add an item to list view
@param label: The label associated with the item.
@param imagePath: Path to image for the icon."""
if os.path.exists(imagePath):
icon = QIcon(imagePath)
else:
icon = QIcon(':/res/Unknown-person.gif')
item = QStandardItem(icon, label)
item.setEditable(True)
# Add image path to the UserRole field.
item.setData(imagePath, Qt.UserRole)
# Add cluster label to image. CLUSTER_ROLE is where I intend
# to put the item's cluster label.
item.setData(self.UNCLUSTERED_LABEL, self.CLUSTER_ROLE)
# Prevent an item from dropping into another item.
item.setDropEnabled(False)
# Add item to list indirectly by adding it to the model.
self._dataModel.appendRow(item)
def clear(self):
self._dataModel.clear()
嗨。首先,感謝您的回覆。我已經嘗試過你的測試代碼,並且實際上FacesView類的排序工作。我通過在每個臉部圖標的文本標籤中顯示羣集標籤來跟蹤您的示例,看起來羣集正確執行,但具有相同羣集標籤的項目仍然不相鄰。 – lightalchemist
我懷疑排序不起作用,因爲我如何配置我的列表。 FacesView的viewMode屬性最初設置爲IconMode,其移動屬性設置爲靜態。將viewMode更改爲ListMode和移動到Snap並沒有幫助。任何想法我應該檢查哪些屬性?謝謝。 – lightalchemist
嗨,我想通了。你是對的,問題在於標籤,特別是標籤的「類型」。我從一個庫中獲得了集羣標籤,它們將它們作爲一個dtype = int32的numpy數組返回。由於某些原因,即使代碼能夠使用其中的值來更新文本標籤和CLUSTER_ROLE字段,也無法使用它們對元素進行排序。如果我使用「labels.tolist()」將numpy數組轉換爲列表或使用「labels = map(int,labels」)將元素映射到整數,則排序工作。謝謝! – lightalchemist