mvc(QSortFilterProxyModel)中的自定义排序仅适用一次
Posted
技术标签:
【中文标题】mvc(QSortFilterProxyModel)中的自定义排序仅适用一次【英文标题】:custom sorting in mvc (QSortFilterProxyModel) only works once 【发布时间】:2012-06-26 07:22:39 【问题描述】:我正在尝试在 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
这是完整的测试代码: 导入系统 从 PySide.QtGui 导入 * 从 PySide.QtCore 导入 *
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_() )
【问题讨论】:
更改组合框值后尝试使用model.invalidate() 【参考方案1】:基本上Qt“认为”你的代理已经排序。准确地说,它在 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 )
【讨论】:
以上是关于mvc(QSortFilterProxyModel)中的自定义排序仅适用一次的主要内容,如果未能解决你的问题,请参考以下文章
QSortFilterProxyModel 仅对获取的数据进行排序
QSortFilterProxyModel 不更新 QTableview
QSortFilterProxyModel 打破 columnWidths