3

PySide でモデル/ビュー構造のカスタム ソート動作を設定しようとしています。すべてのアイテムは辞書であり、それらのキーでフィルター処理する必要があります (これらの辞書のテーブル ビューではなく、それぞれを 1 つのエンティティとして提示する必要があります)。

QSortFilterProxyModel から継承し、lessThan メソッドを再実装しました。並べ替えウィジェットが初めて変更されたとき (プロキシの sort() メソッドがトリガーされたとき) は正常に動作しますが、その後、lessThan メソッドは呼び出されなくなりました。理由はわかりませんが、ここで助けを得たいと思っています。それが解決策である場合、別の方法でこれに取り組む方法の提案を喜んで検討します。

これは私のプロキシです:

class ProxyModel ( QSortFilterProxyModel ):
    def __init__( self, parent=None ):
        super( ProxyModel, self).__init__( parent )
        self.setFilterCaseSensitivity( Qt.CaseInsensitive )
        self.setSortCaseSensitivity( Qt.CaseInsensitive )
        self.setDynamicSortFilter( True )

    def sortBy( self, attr ):
        print 'sorting by', attr
        self.__sortBy = attr
        self.sort( 0, Qt.AscendingOrder ) # THIS DOES NOT GET CALLED WHEN THE COMBO BOX CHANGES A SECOND TIME

    def lessThan( self, left, right ):
        '''Custom sorting behaviour'''
        leftTool = ( self.sourceModel().itemFromIndex( left ) )
        rightTool = ( self.sourceModel().itemFromIndex( right ) )
        leftData = leftTool.data()[ self.__sortBy ]
        rightData = rightTool.data()[ self.__sortBy ]
        return leftData < rightData

完全なテスト コードは次のとおりです。 import sys from PySide.QtGui import * from PySide.QtCore import *

class MainWidget( QWidget ) :
    def __init__( self, parent=None ):
        super( MainWidget, self ).__init__()

        self.listView = MyListView()
        model = MyModel()

        # MODELS AND VIEWS
        self.proxyModel = ProxyModel()
        self.proxyModel.setSourceModel( model )
        self.listView.setModel(self.proxyModel)

        # LAYOUTS
        verticalLayout = QVBoxLayout()
        filterLayout = QHBoxLayout()

        # SORTING WIDGET
        sortLayout = QHBoxLayout()
        sortLabel = QLabel( 'sort:' )
        self.sortWidget = QComboBox()
        self.sortWidget.addItems( ['title', 'author', 'downloads'] )
        self.sortWidget.currentIndexChanged.connect( self.sortTools )

        sortLayout.addWidget( sortLabel )
        sortLayout.addWidget( self.sortWidget )

        verticalLayout.addLayout( filterLayout )
        verticalLayout.addLayout( sortLayout )
        verticalLayout.insertWidget(0, self.listView)

        self.setLayout( verticalLayout )

    def sortTools( self ):
        text = self.sortWidget.currentText()
        self.proxyModel.sortBy( text )

class ProxyModel ( QSortFilterProxyModel ):
    def __init__( self, parent=None ):
        super( ProxyModel, self).__init__( parent )
        self.setFilterCaseSensitivity( Qt.CaseInsensitive )
        self.setSortCaseSensitivity( Qt.CaseInsensitive )
        self.setDynamicSortFilter( True )

    def sortBy( self, attr ):
        print 'sorting by', attr
        self.__sortBy = attr
        self.sort( 0, Qt.AscendingOrder ) # THIS DOES NOT GET CALLED WHEN THE COMBO BOX CHANGES A SECOND TIME

    def lessThan( self, left, right ):
        '''Custom sorting behaviour'''
        leftTool = ( self.sourceModel().itemFromIndex( left ) )
        rightTool = ( self.sourceModel().itemFromIndex( right ) )
        leftData = leftTool.data()[ self.__sortBy ]
        rightData = rightTool.data()[ self.__sortBy ]
        return leftData < rightData


class MyListView( QListView ):
    def __init__( self, parent=None ):
        super( MyListView, self).__init__( parent )
        self.setEditTriggers( QListView.NoEditTriggers )
        self.setViewMode( QListView.IconMode )
        self.setMovement( QListView.Static )
        self.setResizeMode( QListView.Adjust )
        self.setDragEnabled( True )


class MyModel( QStandardItemModel ):
    def __init__( self, parent=None ):
        super( MyModel, self).__init__( parent )
        self.init_data()

    def init_data(self):
        row = 0
        toolData = [ {'title':'ToolA', 'author':'John Doe', 'downloads':123, 'category':'color'},
                     {'title':'ToolB', 'author':'me', 'downloads':13, 'category':'color'},
                     {'title':'ToolC', 'author':'you', 'downloads':321, 'category':'transform'},
                     {'title':'ToolD', 'author':'unknown', 'downloads':2, 'category':'transform'}]

        for tool in toolData:
            item = QStandardItem( '%(title)s by %(author)s (%(category)s) - %(downloads)s downloads' % tool )
            item.setData( tool )
            self.setItem( row, 0, item )
            row += 1




if __name__ == '__main__':
    app = QApplication( sys.argv )

    mainWidget = MainWidget()
    mainWidget.resize( 400, 400 )
    mainWidget.show()

    sys.exit( app.exec_() )
4

1 に答える 1

2

基本的に、Qt は Proxy が既にソートされていると「考えます」。正確には、C++ で次のことをチェックします。

(d->dynamic_sortfilter && 
 d->proxy_sort_column == column && 
 d->sort_order == order)

したがって、問題を解決するには、dynamic_sortfilter を False に設定するか (副作用があります)、並べ替えを無効にすることができます。

def sortBy( self, attr ):
    print 'sorting by', attr
    self.__sortBy = attr
    self.invalidate() #invalidate helps 
    self.sort( 0, Qt.AscendingOrder )
于 2012-06-26T09:24:55.713 に答える