此问题与this未回答的问题完全相同,只是我使用的是Python。
我有这个。
我正在寻找这个。
我正在寻找如何解决这个问题的提示。这是我到目前为止所考虑的内容。
帮助!
源。
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_()
为清楚起见,这个问题是关于QListView而不是关于它的替代品。原因是应用程序的其余部分正在以类似MVC的方式开发,其中一个或多个视图正在绘制一个模型中存在的唯一数据集。
这个特殊的视图包括部分,其他视图,不一定是QListView的,不应该对部分有所了解。例如,一个视图可以是计数器,列出可用项目的数量。另一个可能是馅饼,显示以字母“A”开头的项目之间的比率。
为了进一步参考,我正在寻找的是ListView在QML中的作用。
也就是说,单个模型带有可选节的附加委托。在这种情况下,视图不需要模型包含这些添加的成员,而是根据现有数据绘制它们。
好的,所以我使用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_()
答案 0 :(得分:2)
你想要的是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
来绘制部分项目,而不是标签项目。
答案 1 :(得分:1)
好的,您打算将其他视图(例如饼图)连接到QAbstractListModel
后代。我想这是可能的,但这并不常见。因此混乱。 IHMO的Qt模型类并不是那么好,如果我没有表或树视图,我也不会使用它们。没有什么能阻止你制作自己的模型类并从中填充QListWidget
。
但是,我们仍然希望您将数据放在QAbstractListModel
中。我同意将这些部分添加为虚拟物品是一个坏主意,因此您的选项1已经用完了。
我认为使用代理模型是一个不错的选择。您可以将所有QListViews
连接到代理,将所有其他视图(例如饼图)连接到基础源模型。代理模型 然后将这些部分包含为项目。我认为您只需要一个代理,因为所有列表视图的部分都是相同的。
您可以使用委托来自定义单元格的呈现方式,而不是从QListView
继承子类。请查看Qt文档中的star delegate example。
选项4,编写自己的视图,应该是您的最后选择。你基本上推出了自己的版本QListView。这是很多工作,永远不会像Qt原版那么好。
希望这有帮助。