我正在尝试在 PySide 中为我的模型/视图结构设置自定义排序行为。所有项目都是字典,我需要按它们的键进行过滤(我不是在查看这些字典的表格视图,而是需要将它们分别呈现为一个实体)。
我继承自 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_() )