我在使用我指定的字段中的值对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