有没有办法在PySide或PyQt中添加章节到QListView?

这个问题与这个未答复的问题完全相同,除了我在使用Python。

我有这个。

我正在寻找这个。

我正在寻找如何解决这个问题的提示。 这是我迄今为止所考虑的。

  • 将“虚拟物品”添加到模型本身。 我宁愿不这样做,为了保持模型免费的视图相关数据。 我打算在此模型上添加其他视图。
  • 为每个视图添加一个代理模型。 该代理可以添加其他项目并对其进行适当的排序。 虽然比(1)更干净,但我并不完全相信这个原因。
  • 子类QListView,但我很努力去理解要重载的东西。
  • 只写我自己的看法; 使用for-loop和QLabels,并尽可能与模型同步。 要做你必须做的。
  • 帮帮我!

    资源。

    import sys
    from PySide import QtCore, QtGui
    
    
    Label = QtCore.Qt.DisplayRole
    Section = QtCore.Qt.UserRole + 1
    
    
    class Model(QtCore.QAbstractListModel):
        def __init__(self, parent=None):
            super(Model, self).__init__(parent)
            self.items = list()
    
        def data(self, index, role):
            item = self.items[index.row()]
            if role == Label:
                return item["label"]
    
            if role == Section:
                return item["section"]
    
        def append(self, item):
            """Append item to end of model"""
            self.beginInsertRows(QtCore.QModelIndex(),
                                 self.rowCount(),
                                 self.rowCount())
    
            self.items.append(item)
            self.endInsertRows()
    
        def rowCount(self, parent=None):
            return len(self.items)
    
    app = QtGui.QApplication(sys.argv)
    model = Model()
    
    for item in ({"label": "Ben", "section": "Human"},
                 {"label": "Steve", "section": "Human"},
                 {"label": "Alpha12", "section": "Robot"},
                 {"label": "Mike", "section": "Toaster"}):
        model.append(item)
    
    view = QtGui.QListView()
    view.setWindowTitle("My View")
    view.setModel(model)
    view.show()
    
    app.exec_()
    


    更新1 - 其他信息

    为了清楚起见,这个问题是关于QListView而不是替代它。 原因在于应用程序的其余部分正在以类似MVC的方式进行开发,其中一个或多个视图正在绘制一个模型中存在的唯一数据集。

    这个特定的视图包含部分,其他视图(不一定是QListView的视图)不应该知道关于部分的任何内容。 例如,一个视图可能是一个计数器,列出了可用项目的数量。 另一个可能是饼图,显示以字母“A”开头的项目之间的比例。

    为了进一步的参考,我正在寻找的是ListView在QML中所做的。

  • http://doc.qt.io/qt-5/qml-qtquick-listview.html#section-prop
  • 也就是说,具有可选部分的额外代表的单个模型。 在这种情况下,视图不需要模型包含这些添加的成员,而是基于现有数据绘制它们。

  • 资源

  • 更新2 - 正在进行中

    好的,我使用QSortFilterProxyModel将额外的项目添加到视图的底部,但我很努力去理解:

  • 我如何为他们分配相应的数据?
  • 我如何将他们分类到位,在他们的“孩子”项目之上?
  • import sys
    from PySide import QtCore, QtGui
    
    
    Label = QtCore.Qt.DisplayRole
    Section = QtCore.Qt.UserRole + 1
    IsSection = QtCore.Qt.UserRole + 2
    
    
    class Item(object):
        @classmethod
        def paint(cls, painter, option, index):
            rect = QtCore.QRectF(option.rect)
    
            painter.save()
    
            if option.state & QtGui.QStyle.State_MouseOver:
                painter.fillRect(rect, QtGui.QColor("#DEE"))
    
            if option.state & QtGui.QStyle.State_Selected:
                painter.fillRect(rect, QtGui.QColor("#CDD"))
    
            painter.drawText(rect.adjusted(20, 0, 0, 0),
                             index.data(Label))
    
            painter.restore()
    
        @classmethod
        def sizeHint(cls, option, index):
            return QtCore.QSize(option.rect.width(), 20)
    
    
    class Section(object):
        @classmethod
        def paint(self, painter, option, index):
            painter.save()
            painter.setPen(QtGui.QPen(QtGui.QColor("#666")))
            painter.drawText(QtCore.QRectF(option.rect), index.data(Label))
            painter.restore()
    
        @classmethod
        def sizeHint(self, option, index):
            return QtCore.QSize(option.rect.width(), 20)
    
    
    class Delegate(QtGui.QStyledItemDelegate):
        def paint(self, painter, option, index):
            if index.data(IsSection):
                return Section.paint(painter, option, index)
            else:
                return Item.paint(painter, option, index)
    
        def sizeHint(self, option, index):
            if index.data(IsSection):
                return Section.sizeHint(option, index)
            else:
                return Item.sizeHint(option, index)
    
    
    class Model(QtCore.QAbstractListModel):
        def __init__(self, parent=None):
            super(Model, self).__init__(parent)
            self.items = list()
    
        def data(self, index, role):
            item = self.items[index.row()]
    
            return {
                Label: item["label"],
                Section: item["section"],
                IsSection: False
            }.get(role)
    
        def append(self, item):
            self.beginInsertRows(QtCore.QModelIndex(),
                                 self.rowCount(),
                                 self.rowCount())
    
            self.items.append(item)
            self.endInsertRows()
    
        def rowCount(self, parent=None):
            return len(self.items)
    
    
    class Proxy(QtGui.QSortFilterProxyModel):
        def data(self, index, role):
            if index.row() >= self.sourceModel().rowCount():
    
                return {
                    Label: "Virtual Label",
                    Section: "Virtual Section",
                    IsSection: True
                }.get(role)
    
            return self.sourceModel().data(index, role)
    
        def rowCount(self, parent):
            sections = 0
    
            prev = None
            for item in self.sourceModel().items:
                cur = item["section"]
    
                if cur != prev:
                    sections += 1
    
                prev = cur
    
            # Note: This includes 1 additional, duplicate, section
            # for the bottom item. Ordering of items in model is important.
            return self.sourceModel().rowCount() + sections
    
        def index(self, row, column, parent):
            return self.createIndex(row, column, parent)
    
        def mapToSource(self, index):
            if not index.isValid():
                return QtCore.QModelIndex()
    
            return self.sourceModel().createIndex(index.row(),
                                                  index.column(),
                                                  QtCore.QModelIndex())
    
        def parent(self, index):
            return QtCore.QModelIndex()
    
    
    app = QtGui.QApplication(sys.argv)
    model = Model()
    
    for item in ({"label": "Ben", "section": "Human"},
                 {"label": "Steve", "section": "Human"},
                 {"label": "Alpha12", "section": "Robot"},
                 {"label": "Mike", "section": "Toaster"},
                 {"label": "Steve", "section": "Human"},
                 ):
        model.append(item)
    
    proxy = Proxy()
    proxy.setSourceModel(model)
    
    delegate = Delegate()
    
    view = QtGui.QListView()
    view.setWindowTitle("My View")
    view.setModel(proxy)
    view.setItemDelegate(delegate)
    view.show()
    
    app.exec_()
    

    你想要的是一个QTreeWidget (或QTreeView如果你想单独的模型/视图,但你必须创建自己的模型)。

    tree = QtGui.QTreeWidget()
    tree.setHeaderLabels(['Name'])
    
    data = ({"label": "Ben", "section": "Human"},
            {"label": "Steve", "section": "Human"},
            {"label": "Alpha12", "section": "Robot"},
            {"label": "Mike", "section": "Toaster"})
    
    sections = {}
    for d in data:
        sections.setdefault(d['section'], []).append(d['label'])
    
    for section, labels in sections.items():
        section_item = QtGui.QTreeWidgetItem(tree, [section])
        for label in labels:
            QtGui.QTreeWidgetItem(section_item, [label])
    

    唯一的其他选择是使用QListWidget/QListView并使用QItemDelegate绘制您的节项与标签项不同。


    好的,您打算将其他视图(如饼图)连接到QAbstractListModel后代。 我想这是可能的,但它并不常见。 因此混乱。 IHMO Qt Model类并不是那么棒,如果我没有表或树视图,我不会使用它们。 没有什么能阻止你制作你自己的模型类,并从中填充一个QListWidget

    但是让我们假设你仍然想把你的数据放在QAbstractListModel 。 我同意将这些部分添加为虚拟物品是一个糟糕的主意,因此您的选项1已停用。

    我认为使用代理模式是一个不错的选择。 您可以将所有QListViews连接到代理和所有其他视图(例如饼图)以连接到底层源模型。 代理模型然后将这些部分包括为项目。 我认为你只需要一个代理,因为这些部分对于所有列表视图都是相同的。

    您可以使用委托来定制单元格的渲染方式,而不是从QListView进行子类化。 看看Qt文档中的明星代表示例。

    选择4,写下你自己的观点,应该是你最后的选择。 你基本上正在推出你自己的版本QListView。 这是很多工作,并且永远不会像Qt原创那样好。

    希望这可以帮助。

    链接地址: http://www.djcxy.com/p/79003.html

    上一篇: Is there a way to add sections to QListView in PySide or PyQt?

    下一篇: How to build with a custom eglfs cursor atlas?