2012-06-26 62 views
3

我想在PySide中爲我的模型/視圖結構設置自定義排序行爲。 所有項目都是字典,我需要按鍵過濾(我不是在這些字典的表格視圖之後,而是需要將它們呈現爲一個實體)。mvc(QSortFilterProxyModel)中的自定義排序只能工作一次

我繼承自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 

這裏是完整的測試代碼: 進口SYS 從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_()) 
+0

嘗試使用model.invalidate()後組合框的值發生變化 –

+0

太好了,非常感謝 –

回答

2

基本的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)