【问题标题】:sort a QAbstractListModel from python从 python 中对 QAbstractListModel 进行排序
【发布时间】:2018-06-14 21:16:00
【问题描述】:

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

model2.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 我认为 slot sortData() .sortData() 函数不正确

【问题讨论】:

    标签: python python-3.x pyqt qml pyqt5


    【解决方案1】:

    要订购视图,最合适的选项是使用 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有一个例子

    【讨论】:

    • 对不起@eyllanesc
    • 您好,我需要从 qml 中的列表模型中访问数据。 console.log(PersonModel.data(1,'value1')) 是我使用的函数调用。但我得到的结果是“不确定”。那里有什么问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    • 2016-11-12
    • 2018-04-11
    • 2017-07-12
    • 2018-04-17
    • 1970-01-01
    相关资源
    最近更新 更多