【问题标题】:how to sort a multi dimensional model如何对多维模型进行排序
【发布时间】:2012-07-24 21:30:13
【问题描述】:

我正在使用 PySide 编写插件浏览器。可用的插件存储在一个三维模型中,如下所示:

pluginType/pluginCategory/pluginName

例如:

python/categoryA/toolA
python/categoryB/toolAA

等等

在我的自定义视图中,我在列表中显示给定插件类型(即“python”)的所有工具,无论它们的类别如何:

(python)
categoryA/toolA
categoryA/toolB
categoryA/toolC
categoryB/toolAA
categoryB/toolBB
categoryB/toolCC

我现在想知道如何最好地对该视图进行排序,以便工具按名称排序,而不管它们的父类别如何。我当前代理模型中的排序方法会为每个类别生成一个排序列表,就像上面的一样,但我所追求的是:

(python)
categoryA/toolA
categoryB/toolAA
categoryA/toolB
categoryB/toolBB
categoryA/toolC
categoryB/toolCC

我是否必须让我的代理模型将多维源模型转换为一维模型才能实现这一点,还是有更好的方法?我希望能够将自定义视图与标准树视图同步,这就是我选择多维模型的原因。

谢谢, 坦率的

编辑 1: 这是我作为简化示例的内容。我不确定这是否是解决方法(将模型结构更改为一维模型),如果是,我不确定如何在代理模型中正确创建数据,所以它是按预期与源模型链接。

import sys
from PySide.QtGui import *
from PySide.QtCore import *

class ToolModel(QStandardItemModel):
    '''multi dimensional model'''
    def __init__(self, parent=None):
        super(ToolModel, self).__init__(parent)
        self.setTools()

    def setTools(self):
        for contRow, container in enumerate(['plugins', 'python', 'misc']):
            contItem = QStandardItem(container)
            self.setItem(contRow, 0, contItem)
            for catRow, category in enumerate(['catA', 'catB', 'catC']):
                catItem = QStandardItem(category)
                contItem.setChild(catRow, catItem)
                for toolRow, tool in enumerate(['toolA', 'toolB', 'toolC']):
                    toolItem = QStandardItem(tool)
                    catItem.setChild(toolRow, toolItem)

class ToolProxyModel(QSortFilterProxyModel):
    '''
    proxy model for sorting and filtering.
    need to be able to sort by toolName regardless of category,
    So I might have to convert the data from sourceModel to a 1-dimensional model?!
    Not sure how to do this properly.
    '''
    def __init__(self, parent=None):
        super(ToolProxyModel, self).__init__(parent)

    def setSourceModel(self, model):
        index = 0
        for contRow in xrange(model.rowCount()):
            containerItem = model.item(contRow, 0)
            for catRow in xrange(containerItem.rowCount()):
                categoryItem = containerItem.child(catRow)
                for itemRow in xrange(categoryItem.rowCount()):
                    toolItem = categoryItem.child(itemRow)
                    # how to create new, 1-dimensional data for self?



app = QApplication(sys.argv)
mainWindow = QWidget()
mainWindow.setLayout(QHBoxLayout())

model = ToolModel()
proxyModel = ToolProxyModel()
proxyModel.setSourceModel(model)
treeView = QTreeView()
treeView.setModel(model)
treeView.expandAll()
listView = QListView()

listView.setModel(proxyModel)

mainWindow.layout().addWidget(treeView)
mainWindow.layout().addWidget(listView)
mainWindow.show()
sys.exit(app.exec_())

编辑: 或者我应该问如何最好地准备一个源模型,以便 QTreeView 可以使用它,但也可以按照上述方式排序以显示在列表视图中?!

【问题讨论】:

  • 我想我不明白。您没有 3 个 CatACatB,您有 1 个,每个有 3 个孩子。这将如何与您的排序一起工作?你想分离这些孩子并复制CatACatB等...?
  • 这正是我想要理解的;是否可以编写一个代理模型,它可以为我提供上述以分层模型为源的排序行为。也许我应该从“平面”源模型(即每行一个项目且没有层次结构)开始,然后使用代理模型来创建 TreeView?我可以从附加到工具的属性中推导出层次结构。
  • 我仍在尝试理解您的意图。如果不将其中的项目分组,那些Cat* 的目的是什么?有了你的排序,我会觉得很奇怪。也许您应该切换层次顺序:Tool-Category。这样感觉会自然很多。除此之外,您当然可以通过子类化QSortFilterProxy 并根据您的需要重新实现lessThan 来定义自定义排序(即根据子级排序),但是对于您希望它的工作方式,您需要将这些子级分开,以便每个类别有 1 个孩子。
  • 它只是一个特殊的视图,它在一个网格/列表中显示所有类别中的所有工具,然后允许用户过滤到特定类别的工具。
  • 这是一个特殊的视图,它列出了容器中的所有工具(顶级,例如“python”),而不管它们的类别(在这种情况下,类别只是工具的一个属性)。或者,我希望可以选择显示一个树视图,其中显示了容器/类别/工具。我已经继承了 QSortFilterProxy 并实现了 lessThan,但这不会遍历工具的父级(类别)。换句话说,我试图基于同一模型显示两个不同的层次结构。一个作为类型/类别/工具,另一个作为类型/工具

标签: model-view-controller qt pyqt4 pyside


【解决方案1】:

使用 QTableView 并按 tool_name 列排序(使用排序代理)。

【讨论】:

    猜你喜欢
    • 2017-07-03
    • 2021-07-02
    • 2017-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-13
    • 2010-10-13
    • 2011-10-29
    相关资源
    最近更新 更多