免责声明:我为这个话题找到了不同的类似答案,但我找不到解决我的问题的答案。
我有下面的源代码模型结构,它由一个单列的无头QTreeView显示
- Cat 1
|-- Cat1_El1
|-- ...
|-- Cat1_ElL
...
- Cat N
|-- CatN_El1
|-- ...
|-- CatN_ElM视图和源模型工作得很好。每个低级项目都是由用户动态创建的,而类别则是硬编码的。
现在,核心问题如下:基于某个条件,我可以通过实例化的代理模型的额外属性轻松管理,我希望在QComboBox中显示特定类别的所有项。我想过重新实现QAbstractProxyModel,但我面临着一些麻烦,无法理解如何重新实现Qt Doc声明的mapFromSource和mapToSource这两个方法。我想出来的东西如下所示。我所有的怀疑和推断都被报告为评论,因为我认为它更清晰。注意,我是用Python语言编写代码,使用PyQt5,但实际上我更感兴趣的是如何重新实现代理的概念,而不是代码本身(因此,C++代码也可以很好地工作)
class GWModulesComboProxy(QIdentityProxyModel):
# This re-implements the basic proxy structure
def __init__(self, moduleType : CategoriesType, parent: Optional[QObject]) -> None:
# `CategoriesType` --> See later `ComboProxyCatN`
self.moduleType = moduleType
super().__init__(parent)
def index(self, row: int, column: int, parent: QModelIndex) -> QModelIndex:
# Based upon the crash of the model when clicking on the combobox, I'm inferring that I should re-implementing
# this method and call, FROM it, the `mapToSource`. But I can't figure out how
pass
def mapFromSource(self, sourceIndex: QModelIndex) -> QModelIndex:
if not sourceIndex.isValid():
return QModelIndex()
# If the node is a root node (i.e. a Cathegory itself), it will never show up into the ComboBox
if not sourceIndex.parent().isValid():
return QModelIndex()
# Into the source model, the root nodes are ordered against the IntEnum CategoriesType --> See later `ComboProxyCatN`
if sourceIndex.parent().row() == self.moduleType:
return sourceIndex
return QModelIndex()
def mapToSource(self, proxyIndex: QModelIndex) -> QModelIndex:
if not proxyIndex.isValid():
return QModelIndex()
parent = self.sourceModel().index(self.moduleType, 1, QModelIndex())
return self.sourceModel().index(proxyIndex.row(), proxyIndex.column(), parent)
def data(self, proxyIndex: QModelIndex, role: int) -> Any:
# I was guessing that re-implementing `data` was meaningless since the data should be already taken from the source
# by means of the mapper methods. Am I correct?
pass
def columnCount(self, parent: QModelIndex) -> int:
return 1
class ComboProxyCatN(ComboProxy):
# Just an example how to manage the specific Category N
def __init__(self, parent: Optional[QObject]) -> None:
# CategoriesType is an IntEnum that stores the different cathegories
super().__init__(CategoriesType.CatN, parent)发布于 2021-08-03 15:18:22
要显示树的分支,不需要使用代理模型,而是必须通过QComboBox的setRootModelIndex()方法来指示根。
下面的示例显示了类别"Cat 5“的分支:
import random
from PyQt5 import QtCore, QtGui, QtWidgets
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
model = QtGui.QStandardItemModel()
for i in range(1, 10):
root_item = QtGui.QStandardItem(f"Cat {i}")
model.appendRow(root_item)
for j in range(1, random.randrange(5, 10)):
child_item = QtGui.QStandardItem(f"Cat{i}_El{j}")
root_item.appendRow(child_item)
view = QtWidgets.QTreeView()
view.setModel(model)
view.expandAll()
category = "Cat 5"
root_index = QtCore.QModelIndex()
indexes = model.match(
model.index(0, 0), QtCore.Qt.DisplayRole, category, flags=QtCore.Qt.MatchExactly
)
if indexes:
root_index = indexes[0]
# or fifth row
# root_index = model.index(4, 0)
combobox = QtWidgets.QComboBox()
combobox.setModel(model)
combobox.setRootModelIndex(root_index)
combobox.setCurrentIndex(0)
widget = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(widget)
lay.addWidget(view)
lay.addWidget(combobox)
widget.resize(640, 480)
widget.show()
sys.exit(app.exec_())https://stackoverflow.com/questions/68638358
复制相似问题