具有多个 header 的 QStandardItemModel - 将 QTreeView header 与模型分离
QStandardItemModel with multiple headers - decouple QTreeView header from model
我有一个 QStandardItemModel,在不同的视图中需要不同的水平 header 标签。
我无法找到有关如何以这种方式将 QTreeView 的 header 与模型分离的信息。这可能吗?
请参阅下面的简单代码示例。
在这个例子中 - 我们有 ItemTypeA,这是我们的顶级项目,它的水平轴代表属性“名称 | 插值 | 规范化”。
ItemTypeA (ItemTypeB) 的 children 在水平轴上有代表“名称 | 相乘”的项目
TreeViewA 显示所有内容,TreeViewB 仅显示所选 Top Level Item 的 children(本例中未实现选择连接)。
from PySide.QtGui import *
from PySide.QtCore import *
class MyModel(QStandardItemModel):
def __init__(self):
super(MyModel, self).__init__()
iroot = self.invisibleRootItem()
self.setHorizontalHeaderLabels(['Name', 'Interpolation', 'Normalize'])
def newTopLevelItem(self, name = 'myTopLevelItem'):
item = ItemTypeA(name)
root_item = self.invisibleRootItem()
root_item.appendRow([item]+item.settingItems())
return item
class ItemTypeA(QStandardItem):
def __init__(self, *args, **kwargs):
super(ItemTypeA, self).__init__(*args, **kwargs)
self.s_interpolation =QStandardItem('0')
self.s_normalize = QStandardItem('False')
def settingItems(self):
return [
self.s_interpolation,
self.s_normalize
]
def newChildItem(self, name = 'newChildItem'):
childItem = ItemTypeB( name )
self.appendRow( [childItem]+childItem.settingItems() )
class ItemTypeB(QStandardItem):
def __init__(self, *args, **kwargs):
super(ItemTypeB, self).__init__(*args, **kwargs)
self.s_multiply = QStandardItem('1.0')
def settingItems(self):
return [
self.s_multiply,
]
class TreeViewA(QTreeView):
'''
THIS VIEW Needs the Headers:
Item Name | Interpolation | Normalize
'''
def __init__(self):
super(TreeViewA, self).__init__()
model = MyModel()
self.setModel(model)
newItem = model.newTopLevelItem()
newItem.newChildItem()
class TreeViewB(QTreeView):
'''
THIS VIEW Needs the Headers:
Item Name | Multiply
'''
def __init__(self, sourceView):
super(TreeViewB, self).__init__()
model = sourceView.model()
self.setModel(model)
self.setRootIndex(model.index(0,0))
class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
layout = QHBoxLayout()
viewA = TreeViewA()
viewB = TreeViewB(viewA)
layout.addWidget(viewA)
layout.addWidget(viewB)
self.setLayout(layout)
widget = MyWidget()
widget.show()
想法?
这些情况的解决方案是使用 QIdentityProxyModel,但 PySide 和 PySide 中不存在此 class,因此我们必须使用类似的 class,例如 QSortFilterProxyModel 并覆盖 headerData 方法。
...
class HeaderProxyModel(QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
QSortFilterProxyModel.__init__(self, *args, **kwargs)
self.labels = []
def setHeaderLabels(self, labels):
self.labels = labels
def headerData(self, section,orientation, role = Qt.DisplayRole):
if orientation == Qt.Horizontal and 0 <= section < self.columnCount() and role==Qt.DisplayRole and section < len(self.labels) :
return self.labels[section]
return QSortFilterProxyModel.headerData(self, section, orientation, role)
class TreeViewB(QTreeView):
'''
THIS VIEW Needs the Headers:
Item Name | Multiply
'''
def __init__(self, sourceView):
super(TreeViewB, self).__init__()
model = sourceView.model()
proxy = HeaderProxyModel()
proxy.setSourceModel(model)
proxy.setHeaderLabels(["Name", "Multiply"])
self.setModel(proxy)
self.setRootIndex(proxy.index(0,0))
...
我有一个 QStandardItemModel,在不同的视图中需要不同的水平 header 标签。
我无法找到有关如何以这种方式将 QTreeView 的 header 与模型分离的信息。这可能吗?
请参阅下面的简单代码示例。
在这个例子中 - 我们有 ItemTypeA,这是我们的顶级项目,它的水平轴代表属性“名称 | 插值 | 规范化”。
ItemTypeA (ItemTypeB) 的 children 在水平轴上有代表“名称 | 相乘”的项目
TreeViewA 显示所有内容,TreeViewB 仅显示所选 Top Level Item 的 children(本例中未实现选择连接)。
from PySide.QtGui import *
from PySide.QtCore import *
class MyModel(QStandardItemModel):
def __init__(self):
super(MyModel, self).__init__()
iroot = self.invisibleRootItem()
self.setHorizontalHeaderLabels(['Name', 'Interpolation', 'Normalize'])
def newTopLevelItem(self, name = 'myTopLevelItem'):
item = ItemTypeA(name)
root_item = self.invisibleRootItem()
root_item.appendRow([item]+item.settingItems())
return item
class ItemTypeA(QStandardItem):
def __init__(self, *args, **kwargs):
super(ItemTypeA, self).__init__(*args, **kwargs)
self.s_interpolation =QStandardItem('0')
self.s_normalize = QStandardItem('False')
def settingItems(self):
return [
self.s_interpolation,
self.s_normalize
]
def newChildItem(self, name = 'newChildItem'):
childItem = ItemTypeB( name )
self.appendRow( [childItem]+childItem.settingItems() )
class ItemTypeB(QStandardItem):
def __init__(self, *args, **kwargs):
super(ItemTypeB, self).__init__(*args, **kwargs)
self.s_multiply = QStandardItem('1.0')
def settingItems(self):
return [
self.s_multiply,
]
class TreeViewA(QTreeView):
'''
THIS VIEW Needs the Headers:
Item Name | Interpolation | Normalize
'''
def __init__(self):
super(TreeViewA, self).__init__()
model = MyModel()
self.setModel(model)
newItem = model.newTopLevelItem()
newItem.newChildItem()
class TreeViewB(QTreeView):
'''
THIS VIEW Needs the Headers:
Item Name | Multiply
'''
def __init__(self, sourceView):
super(TreeViewB, self).__init__()
model = sourceView.model()
self.setModel(model)
self.setRootIndex(model.index(0,0))
class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
layout = QHBoxLayout()
viewA = TreeViewA()
viewB = TreeViewB(viewA)
layout.addWidget(viewA)
layout.addWidget(viewB)
self.setLayout(layout)
widget = MyWidget()
widget.show()
想法?
这些情况的解决方案是使用 QIdentityProxyModel,但 PySide 和 PySide 中不存在此 class,因此我们必须使用类似的 class,例如 QSortFilterProxyModel 并覆盖 headerData 方法。
...
class HeaderProxyModel(QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
QSortFilterProxyModel.__init__(self, *args, **kwargs)
self.labels = []
def setHeaderLabels(self, labels):
self.labels = labels
def headerData(self, section,orientation, role = Qt.DisplayRole):
if orientation == Qt.Horizontal and 0 <= section < self.columnCount() and role==Qt.DisplayRole and section < len(self.labels) :
return self.labels[section]
return QSortFilterProxyModel.headerData(self, section, orientation, role)
class TreeViewB(QTreeView):
'''
THIS VIEW Needs the Headers:
Item Name | Multiply
'''
def __init__(self, sourceView):
super(TreeViewB, self).__init__()
model = sourceView.model()
proxy = HeaderProxyModel()
proxy.setSourceModel(model)
proxy.setHeaderLabels(["Name", "Multiply"])
self.setModel(proxy)
self.setRootIndex(proxy.index(0,0))
...