代码之家  ›  专栏  ›  技术社区  ›  Neethu

从python对QAbstractListModel排序

  •  1
  • Neethu  · 技术社区  · 8 年前

    我是python和qt的初学者。我需要根据list的一个属性对python中创建的QAbstractList进行排序。我使用了sorted()方法。但是当我运行代码时,python停止工作。你能帮忙吗。从Qml中,我调用了插槽sortData()。我认为sortData()函数不正确 我的代码是

    型号2.py

    from PyQt5.QtCore import QAbstractListModel, Qt, pyqtSignal, pyqtSlot
    from PyQt5.QtCore import QSortFilterProxyModel
    
    class PersonModel(QAbstractListModel):
    
        Name = Qt.UserRole + 1
        value1 = Qt.UserRole + 2
        value2 = Qt.UserRole + 3
        value3 = Qt.UserRole + 4
        value4 = Qt.UserRole + 5
    
        personChanged = pyqtSignal()
    
        def __init__(self, parent=None):
            super().__init__(parent)
            self.persons = [
                {'name': 'item1', 'value1': 10.66, 'value2':10.78, 'value3':10.94, 'value4':10.90},
                {'name': 'item1', 'value1': 10.56, 'value2':10.78, 'value3':10.34, 'value4':10.90},
                {'name': 'item2', 'value1': 10.66, 'value2':10.88, 'value3':10.44, 'value4':10.30}
            ]
            self.i=0
            print(self.persons)
    
        def data(self, QModelIndex, role):
            row = QModelIndex.row()
            if role == self.Name:
                return self.persons[row]['name']
            if role == self.value1:
                return self.persons[row]['value1']
            if role == self.value2:
                return self.persons[row]['value2']
            if role == self.value3:
                return self.persons[row]['value3']
            if role == self.value4:
                return self.persons[row]['value4']
    
    
        def rowCount(self, parent=None):
            return len(self.persons)
    
        def roleNames(self):
            return {
                Qt.UserRole + 1: b'name',
                Qt.UserRole + 2: b'value1',
                Qt.UserRole + 3: b'value2',
                Qt.UserRole + 4: b'value3',
                Qt.UserRole + 5: b'value4'
            }
    
        @pyqtSlot()
        def addData(self):
            self.beginResetModel()
            self.persons = self.persons.append({'name': 'peter', 'value1': 22, 'value2':30, 'value3':40, 'value4':50})
            self.endResetModel()
            print(self.persons)
    
        @pyqtSlot()
        def editData(self):
            print(self.model.persons)
    
        @pyqtSlot(int)
        def sortData(self):
            self.beginResetModel()
            self.persons = sorted(self.persons, key=lambda x: float(x[1]))
            sorted(self.persons)
            #sorted_x = sorted(self._persons, key=lambda role: self.value1)
            #print(sorted_x)
            #self.persons.sort(2, key=Qt.AscendingOrder)
            self.endResetModel()
            print(self.persons)
    

    你好py公司

    import sys, model2
    from PyQt5.QtCore import QUrl
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtQuick import QQuickView
    from PyQt5.QtCore import QSortFilterProxyModel
    
    from os import path
    import PyQt5
    import sys, model2
    
    from PyQt5.QtCore import *
    from PyQt5.QtCore import pyqtProperty, QObject, pyqtSignal
    from PyQt5.QtGui import QGuiApplication
    from PyQt5.QtQml import QQmlApplicationEngine
    from PyQt5.QtCore import pyqtProperty, QCoreApplication, QObject, QUrl
    from PyQt5.QtQml import qmlRegisterType, QQmlComponent, QQmlEngine, QQmlListProperty
    from PyQt5.QtCore import QTimer, pyqtSignal,pyqtSlot
    from PyQt5.QtQml import QQmlListProperty
    
    import sys, model2
    from PyQt5.QtCore import QUrl
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtQuick import QQuickView
    #import QSortFilterProxyModel
    
    import imageResources
    import fontResources
    
    class MainWindow(QQuickView):
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.model = model2.PersonModel()
            self.proxyModel = QSortFilterProxyModel();
            self.proxyModel.setSourceModel(self.model)
            self.rootContext().setContextProperty('PersonModel', self.model)
            self.rootContext().setContextProperty('MainWindow', self)
            self.proxyModel.sort(2,Qt.AscendingOrder)
            self.setSource(QUrl('main.qml'))
    
    myApp = QApplication(sys.argv)
    ui = MainWindow()
    ui.show()
    sys.exit(myApp.exec_())
    

    从Qml中,我调用了插槽sortData()。我认为sortData()函数不正确

    1 回复  |  直到 8 年前
        1
  •  1
  •   eyllanesc    4 年前

    为了排序视图,最合适的选项是使用QSortProxyModel,但这只在Python端起作用,如果我们想将该方法公开给QML,我们必须进行一些修改,因此创建一个从QSortProxyModel继承的类并添加该方法:

    class SortProxyModel(QSortFilterProxyModel):
        @pyqtSlot(str, Qt.SortOrder)
        def sortData(self, roleName, order):
            if order == Qt.InitialSortOrderRole:
                self.setSortRole(order)
                self.invalidate()
            else:
                roles = [key for key, value in self.roleNames().items() if value == roleName.encode()]
                if len(roles) > 0:
                    self.setSortRole(roles[0])
                    self.sort(0, order)
    

    然后你要做的是将原始模型作为基础传递 setSourceModel() ,这个新模型是您必须传递给qml的。

    if __name__ == '__main__':
        myApp = QGuiApplication(sys.argv)
        engine = QQmlApplicationEngine()
        model = PersonModel()
        proxyModel = SortProxyModel()
        proxyModel.setSourceModel(model)
        engine.rootContext().setContextProperty('mymodel', proxyModel)
        engine.load(QUrl.fromLocalFile(QDir.current().absoluteFilePath('main.qml')))
        if len(engine.rootObjects()) == 0:
            sys.exit(-1)
        sys.exit(myApp.exec_())
    

    在以下内容中 link 有一个例子