1

QListView指定したフィールドの値を使用して、アイテムの並べ替えに問題があります。

基本的に私がやろうとしていることはこれです:

  1. 写真のコレクションから顔を検出し、QListView
  2. 顔をクラスター化する(画像)
  3. 同じクラスターに属するアイテム(顔画像)を一緒にリストに配置して、ビューを更新します。具体的には、アイテム1、3、5が1つのクラスターにあり、アイテム2、4、6が別のクラスターにある場合、アイテム2、4、6のいずれかが表示される前に、アイテム1、3、5が(任意の順列で)表示される必要があります。またはその逆。

UserRoleこれを行う方法は、リスト内の各フィールドの1つを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()
4

1 に答える 1

1

投稿したコードに問題はありません。ですから、あなたがそれをどのように使っているかに何か問題があるに違いありません。クラスターラベルをどのように生成していますか?

FacesView意図したとおりにソートするクラスを使用したテストスクリプトを次に示します。

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_())
于 2012-10-14T17:29:16.580 に答える