如何使用Qt.UserRole对Qt QListview中的项目进行排序 [英] How to sort items in Qt QListview using Qt.UserRole

查看:203
本文介绍了如何使用Qt.UserRole对Qt QListview中的项目进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用指定的字段中的值对QListView中的项目进行排序时遇到一些问题.

I'm having some problem sorting the items in my QListView using values in a field I specified.

基本上我想做的是这样:

Basically what I'm trying to do is this:

  1. 检测照片集中的面孔并将其显示在QListView
  2. 对面孔(图像)进行聚类
  3. 通过将列表中属于同一群集的项(即面部图像)放在一起来更新视图.具体来说,如果项目1、3、5在一个群集中,而项目2、4、6在另一个群集中,则应该在显示项目2、4、6中的任何一个之前显示项目1、3、5(以任何排列)反之亦然.
  1. Detect faces in a collection of photos and display them in a QListView
  2. Cluster the faces (images)
  3. Update the view by placing items in the list (which are face images) belonging to the same cluster in together. Concretely, if item 1, 3, 5 are in one cluster and items 2, 4, 6 are in another, then items 1, 3, 5 should be displayed (in whatever permutations) before any of items 2, 4, 6 are displayed or vice versa.

我执行此操作的方法是将列表中每个QStandardItemUserRole字段之一设置为群集标签,然后尝试获取QStandardModel根据此UserRole进行排序.然后,这将显示彼此相邻的同一群集中的项目(即在UserRole中具有相同的群集标签).

The way I went about doing this is to set one of the UserRole field for each QStandardItem in my list to the cluster label and then try to get the QStandardModel to sort according to this UserRole. This would then display items in the same cluster (i.e. with the same cluster label in the UserRole) next to each other.

我能够成功设置项目的UserRole,但是即使我将sort角色设置为默认的DisplayRole(即sort),在QStandardModel上调用sort函数也不会对项目进行分类根据每个面孔的文字标签)按预期工作.

I'm able to set the UserRole successfully for the items but calling the sort function on the QStandardModel did not sort the items even though when I set the sort role to be the default DisplayRole (i.e. sort according to the text label of each face) it worked as intended.

谁能告诉我我的代码出了什么问题或提供替代方法?我已经搜索了排序列表,并且在 QSortFilterProxyModel ,但是由于我对Qt还是很陌生,所以我无法使其适应我的情况.

Can anyone tell me what is wrong with my code or offer an alternative method? I've googled sorting list and I found the following link on QSortFilterProxyModel but as I'm quite new to Qt, I'm not able to adapt it to my situation.

首先感谢您的答复.

以下是相关代码:

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()

推荐答案

您发布的代码没有错.因此,您的使用方式一定存在问题.您如何生成群集标签?

There's nothing wrong with the code you posted. So there must be something wrong with how you are using it. How are you generating the cluster labels?

这是一个使用您的FacesView类的测试脚本,该脚本按您的预期排序:

Here's a test script using your FacesView class that sorts as you intended:

from random import randint
from PySide.QtGui import QWidget, QPushButton, QVBoxLayout, QApplication
from facesview import FacesView

class Window(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.list = FacesView(self)
        self.button = QPushButton('Test', self)
        self.button.clicked.connect(self.handleButton)
        layout = QVBoxLayout(self)
        layout.addWidget(self.list)
        layout.addWidget(self.button)

    def handleButton(self):
        labels = []
        self.list.model().setRowCount(0)
        for row in range(10):
            labels.append(randint(0, 3))
            text = 'Item(%d) - Cluster(%d)' % (row, labels[-1])
            self.list.addItem(text, 'icon.png')
        self.list.updateFaceClusters(labels)

if __name__ == '__main__':

    import sys
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

这篇关于如何使用Qt.UserRole对Qt QListview中的项目进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆