【问题标题】:QSortFilterProxyModel by column valueQSortFilterProxyModel 按列值
【发布时间】:2019-04-18 21:05:56
【问题描述】:

表模型数据示例

我有一个带有 tabWidget 的 gui,每个里面都有一个 tableview。每个选项卡都描述了一个文件夹(请参阅列类型),其中包含我从中提取数据的子目录。我想要一个主模型,通过在每个表视图之间附加一个 QSortFilterProxy 模型来驱动所有视图,该模型为每个单独的表视图的“类型”过滤主模型(传递到子类 RenderTypeProxyModel)。奖励:理想情况下,它们也应该被排序,以便最近的视图(见日期列)出现在顶部。 这是我当前的版本,但由于我无法弄清楚的原因,表格仍然是空白的:

import sys
import os
from datetime import datetime
from pprint import pprint
from PySide2 import QtCore, QtGui, QtWidgets

#To be replaced by env variable
pathToProject = "/run/media/centos7/Data/Projects/Programming/Pipeline/SampleProject"
allowedExportTypes = ["img-prv", "img-final", "img-cg", "img-src", "camera"]


class ExportTableModel(QtCore.QAbstractTableModel):
    def __init__(self, exportData, horizontalHeaders, parent=None):
        QtCore.QAbstractTableModel.__init__(self, parent)
        self.__exportData = exportData
        self.__horizontalHeaders = horizontalHeaders

    def rowCount(self, parent):
        return len(self.__exportData)
    def columnCount(self, parent):
        return len(self.__horizontalHeaders)

    def data(self, index, role): #Returns the data stored under the given role for the item referred to by the index.
        if role == QtCore.Qt.DisplayRole:
            row = index.row()
            column = index.column()
            value = self.__exportData[row][column]
            return value

    def headerData(self, section, orientation, role):
        if role == QtCore.Qt.DisplayRole:
            if orientation == QtCore.Qt.Horizontal:
                if section < len(self.__horizontalHeaders):
                    return self.__horizontalHeaders[section]
                else:
                    return "not implemented"

def tableSetup(tableView):
    tableView.setAlternatingRowColors(True)
    tableView.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
    tableView.setSortingEnabled(True)

class RenderTypeProxyModel (QtCore.QSortFilterProxyModel): #Custom Proxy Model
    def __init__(self, type, parent=None):
        super(RenderTypeProxyModel,self).__init__(parent)
        self.__type = type

    def filterAcceptsRow(self, row, parent): #returns true if the given row should be included in the model
        model = self.sourceModel()
        index = model.index(row, 3, parent)
        if model.data(index,QtCore.Qt.DisplayRole) == type:
            return True
        else:
            return False

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    horizontalHeaders = ["status", "comment", "task", "type", "version", "user", "date", "filepath"] #horizontal header data
    #exportData = #insert sample data list of lists here for testing

    tableView = QtWidgets.QTableView()
    tableView.show()

    model = ExportTableModel(exportData,horizontalHeaders)
    proxyModel = RenderTypeProxyModel("img-prv")
    proxyModel.setSourceModel(model)
    tableView.setModel(proxyModel)

    tableSetup(tableView)
    sys.exit(app.exec_())

这里是用于调试的示例数据:https://pastebin.com/AB1XvKju 只需将其输入到 __main__ 方法中的 exportData 变量即可。

【问题讨论】:

    标签: python python-2.7 qtableview pyside2 qsortfilterproxymodel


    【解决方案1】:

    错误是因为type是python中的保留字:

    if model.data(index,QtCore.Qt.DisplayRole) == type:
    

    你必须使用self.__type

    另一方面,如果您想按日期对数据进行排序,则无需启用setSortingEnabled(),只需使用sort()

    from PySide2 import QtCore, QtGui, QtWidgets
    
    #To be replaced by env variable
    allowedExportTypes = ["img-prv", "img-final", "img-cg", "img-src", "camera"]
    
    
    class ExportTableModel(QtCore.QAbstractTableModel):
        def __init__(self, exportData, horizontalHeaders, parent=None):
            super(ExportTableModel, self).__init__(parent)
            self.__exportData = exportData
            self.__horizontalHeaders = horizontalHeaders
    
        def rowCount(self, parent=QtCore.QModelIndex()):
            return len(self.__exportData)
    
        def columnCount(self, parent=QtCore.QModelIndex()):
            return len(self.__horizontalHeaders)
    
        def data(self, index, role=QtCore.Qt.DisplayRole):
            if role == QtCore.Qt.DisplayRole:
                row = index.row()
                column = index.column()
                value = self.__exportData[row][column]
                return value
    
        def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
            if role == QtCore.Qt.DisplayRole and orientation == QtCore.Qt.Horizontal:
                if section < self.columnCount():
                    return self.__horizontalHeaders[section]
                return "not implemented"
    
    def tableSetup(tableView):
        tableView.setAlternatingRowColors(True)
        tableView.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
    
    class RenderTypeProxyModel (QtCore.QSortFilterProxyModel): #Custom Proxy Model
        def __init__(self, _type, parent=None):
            super(RenderTypeProxyModel,self).__init__(parent)
            self.__type = _type
    
        def filterAcceptsRow(self, row, parent):
            _type = self.sourceModel().index(row, 3, parent).data()
            return _type == self.__type
    
        def lessThan(self, left, right):
            fmt = "yyyy-MM-dd hh:mm:ss"
            left_data = self.sourceModel().data(left)
            right_data = self.sourceModel().data(right)
            return QtCore.QDateTime.fromString(left_data, fmt) < QtCore.QDateTime.fromString(right_data, fmt)
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
    
        horizontalHeaders = ["status", "comment", "task", "type", "version", "user", "date", "filepath"] #horizontal header data
        exportData = # ...
        model = ExportTableModel(exportData, horizontalHeaders)
        tab_widget = QtWidgets.QTabWidget()
        for _type in allowedExportTypes:
            tableView = QtWidgets.QTableView()
            c = horizontalHeaders.index("date")
            tableSetup(tableView)
            proxy = RenderTypeProxyModel(_type, tableView)
            proxy.setSourceModel(model)
            proxy.sort(c, QtCore.Qt.AscendingOrder)
            tableView.setModel(proxy)
            tab_widget.addTab(tableView ,_type)
    
        tab_widget.show()
        sys.exit(app.exec_())
    

    更新:

    在下一部分中,我对您的原始代码进行了改进,避免覆盖不必要的方法并添加委托:

    from PySide2 import QtCore, QtGui, QtWidgets
    
    #To be replaced by env variable
    allowedExportTypes = ["img-prv", "img-final", "img-cg", "img-src", "camera"]
    
    
    class DateDelegate(QtWidgets.QStyledItemDelegate):
        def initStyleOption(self, option, index):
            super(DateDelegate, self).initStyleOption(option, index)
            option.text = index.data().toString("yyyy-MM-dd hh:mm:ss")
    
    class ExportTableModel(QtCore.QAbstractTableModel):
        def __init__(self, exportData, horizontalHeaders, parent=None):
            super(ExportTableModel, self).__init__(parent)
            self.__exportData = exportData
            self.__horizontalHeaders = horizontalHeaders
    
        def rowCount(self, parent=QtCore.QModelIndex()):
            return len(self.__exportData)
    
        def columnCount(self, parent=QtCore.QModelIndex()):
            return len(self.__horizontalHeaders)
    
        def data(self, index, role=QtCore.Qt.DisplayRole):
            if role == QtCore.Qt.DisplayRole:
                row = index.row()
                column = index.column()
                value = self.__exportData[row][column]
                header = self.headerData(column, QtCore.Qt.Horizontal)
                if header == "date":
                    value = QtCore.QDateTime.fromString(value, "yyyy-MM-dd hh:mm:ss")
                return value
    
        def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
            if role == QtCore.Qt.DisplayRole and orientation == QtCore.Qt.Horizontal:
                if section < self.columnCount():
                    return self.__horizontalHeaders[section]
                return "not implemented"
    
    def create_tableview():
        tableView = QtWidgets.QTableView()
        tableView.setAlternatingRowColors(True)
        tableView.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
        return tableView
    
    class RenderTypeProxyModel (QtCore.QSortFilterProxyModel):
        def __init__(self, c_type, _type, c_date, model, parent=None):
            super(RenderTypeProxyModel,self).__init__(parent)
            self.setSourceModel(model)
            self.setFilterKeyColumn(c_type)
            self.setFilterFixedString(_type)
            self.sort(c_date, QtCore.Qt.AscendingOrder)
    
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
    
        horizontalHeaders = ["status", "comment", "task", "type", "version", "user", "date", "filepath"] #horizontal header data
        exportData = # ...
        c_date = horizontalHeaders.index("date")
        c_type = horizontalHeaders.index("type")
        tab_widget = QtWidgets.QTabWidget()
        for _type in allowedExportTypes:
            tableView = create_tableview()
            tab_widget.addTab(tableView ,_type)
            proxy = RenderTypeProxyModel(c_type, _type, c_date, model, tableView)
            tableView.setModel(proxy)
            delegate = DateDelegate(tableView)
            tableView.setItemDelegateForColumn(c_date, delegate)
    
        tab_widget.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 是的,你是对的。我至少阅读了 10 次代码,但它从未发现类型错误。有时它只需要另一双眼睛。你能更详细地介绍一下排序吗?这是在代理模型内还是在 tableview 小部件中完成的,您将如何实现它?到目前为止谢谢你:)
    • @jnt 你试过我的解决方案了吗?,已经实现了过滤器和订单,现在我正在努力简化你代码中的更多内容。
    • 我一直在搜索 qt 文档,但找不到 sort() 方法。我也对我的代码的改进非常感兴趣,因为我可能能够从中学到一些东西。谢谢!编辑:啊,刚刚在 QSortFilterProxy 模型文档中发现了 sort ()。
    • 好的,我将其标记为正确答案。我仍然渴望了解您之前回答中提到的改进。祝你有美好的一天:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-18
    • 2021-10-14
    • 2018-12-27
    • 1970-01-01
    • 2017-01-22
    相关资源
    最近更新 更多