在小部件我的实现中,model
是源模型(从QAbstractItemModel
派生(,proxy_model
(从QSortFilterProxyModel派生(是代理,tree
(QTreeView(是表示模型的树。
我想隐藏第一列。我尝试使用tree.hideColumn(0)
,树显示为平面。
- 如果我在代理中对
filterAcceptsColumn
进行子类化,只为第二列返回True,则不会显示任何行。我相信这是因为父/子关系锚定在索引中的第一列上,当代理请求给定索引列1的行数时,模型返回0(如果我理解得很好,这是模型实现中的预期行为( - 如果我将CCD_ 7设置为在用于列索引的模型中返回非0值>0,我可以看到树和行,但模型没有通过
QAbstractItemModelTester
测试,错误如下:
qt.modeltest: FAIL! childIndex != childIndex1 () returned FALSE
我很清楚,在树模型中,子索引必须附加到单亲索引(第一列(。但是,如果源模型的父子关系没有被代理保留,如果第一列被过滤,我应该如何隐藏代理模型中的第一列?我觉得这是一个";bug";或者我错过了什么!
有人知道在不丢失父/子信息的情况下过滤/隐藏树视图中的第一列,并仍然验证qmodel实现的正确方法吗?
谢谢!
一个正确的实现至少需要代理为第二列的父列创建索引,需要index()
、parent()
、mapToSource()
和mapFromSource()
的正确实现。对于树模型来说,这可能非常棘手。
如果源模型不是太复杂,并且它的所有功能都得到了正确实现,那么一个可能的解决方法就是只覆盖代理的data()
(和headerData
(,并始终返回下一列的同级。
下面的测试是用一个简单的QStandardItemModel完成的,但我认为使用QAbstractItemModel不应该有任何不同,只要它得到了正确的实现。
from PyQt5 import QtCore, QtGui, QtWidgets
class ColumnSwapProxy(QtCore.QSortFilterProxyModel):
def data(self, index, role=QtCore.Qt.DisplayRole):
return super().data(index.sibling(index.row(), index.column() + 1), role)
def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
if orientation == QtCore.Qt.Horizontal:
section += 1
return super().headerData(section, orientation, role)
class Test(QtWidgets.QWidget):
def __init__(self):
super().__init__()
layout = QtWidgets.QVBoxLayout(self)
self.combo = QtWidgets.QComboBox()
layout.addWidget(self.combo)
self.tree = QtWidgets.QTreeView()
layout.addWidget(self.tree)
self.model = QtGui.QStandardItemModel()
self.createTree(self.model.invisibleRootItem())
self.tree.setModel(self.model)
self.model.setHorizontalHeaderLabels(
['Root', 'Fake root'] + ['Col {}'.format(c) for c in range(2, 6)])
self.tree.header().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
self.proxy = ColumnSwapProxy()
self.proxy.setSourceModel(self.model)
self.combo.addItem('Base model', self.model)
self.combo.addItem('First column hidden', self.proxy)
self.combo.currentIndexChanged.connect(self.setModel)
def setModel(self):
model = self.combo.currentData()
self.tree.setModel(model)
lastColumn = self.model.columnCount() - 1
self.tree.header().setSectionHidden(lastColumn, model == self.proxy)
def createTree(self, parent, level=0):
for r in range(10):
first = QtGui.QStandardItem('Root {} (level {})'.format(level + 1, r + 1))
if level < 2 and not r & 3:
self.createTree(first, level + 1)
row = [first]
for c in range(5):
row.append(QtGui.QStandardItem(
'Column {} (level {})'.format(c + 2, level + 1)))
parent.appendRow(row)
import sys
app = QtWidgets.QApplication(sys.argv)
w = Test()
w.show()
sys.exit(app.exec_())