【发布时间】:2021-02-24 17:48:27
【问题描述】:
我正在尝试创建一个可用于 QTableView 和 QTreeView 的模型。例如,我的数据类似于:
| ID | Location | Name |
|---|---|---|
| 101 | 201 | Apple |
| 201 | None | Kitchen |
| 102 | 201 | Banana |
| 301 | None | Cellar |
| 302 | 301 | Potatoes |
| 202 | 302 | Nail |
所以每个条目都有一个位置,该位置本身就是模型中的一个条目。对于 QTableView,我想简单地显示所有条目,如上所示,而对于 QTreeView,我想要类似的东西
- 201:厨房
- 101:苹果
- 102:香蕉
- 301:地窖
- 302:土豆
- 202:钉子
- 302:土豆
然而,我的问题是我无法弄清楚如何实现 QAbstractProxyModel.maptoSource() 或 mapfromSource(),因为我丢失了 QTableView 中有关父级的信息。阅读https://www.qtcentre.org/threads/26163-Map-table-to-tree-through-model-view-possible 似乎这根本不可能。然而 QAbstractProxyModel 明确表示这是为了在两个视图中显示数据。谁能指出我正确的方向或知道是否可以实现这样的模型?特别是在 Python 中,很遗憾我找不到任何示例。
我真的很喜欢将未缩进的 TreeView 用作一种 TableView 的想法。不幸的是,我仍然无法创建模型。目前,仅显示顶部条目。
class MyModel(qtg.QStandardItemModel):
def __init__(
self,
engine
):
self.engine = engine
self.hierarchy_key = 'location_id'
self.column_names = ['id', 'location_id', 'name', 'quantity']
super().__init__(0, len(self.fields))
self.setHorizontalHeaderLabels(self.column_names)
self.root = self.invisibleRootItem()
self.build_model()
def build_model(self):
def add_children_to_tree(entries, parent_item):
for entry in entries:
items = []
for col in self.column_names:
text = getattr(entry, col)
item = qtg.QStandardItem(text)
items.append(qtg.QStandardItem(text))
parent_item.appendRow(items)
item = items[1] #the location_id item
parent_item.setChild(item.index().row(), item.index().column(), item)
with session_scope(self.engine) as session:
child_entries = (
session.query(self.entry_type)
.filter(
getattr(getattr(self.entry_type, self.hierarchy_key), "is_")(
entry.id
)
)
.all()
)
if child_entries:
add_children_to_tree(child_entries, item)
self.removeRows(0, self.rowCount())
with session_scope(self.engine) as session:
root_entries = session.query(self.entry_type).filter(getattr(getattr(self.entry_type, self.hierarchy_key), "is_")(None)).all()
if not isinstance(root_entries, list):
root_entries = [root_entries]
add_children_to_tree(root_entries, self.root)
这个想法是会话查询会产生一个条目列表。每个条目都是数据库中的一条记录,具有“id”、“location_id”等属性。因此,每个属性都是一个项目,项目列表在模型中创建一行。我无法弄清楚如何以此处显示的方式使该行项目成为另一行的子项: 我假设 setChild() 函数需要以不同的方式调用?
【问题讨论】:
-
“我在 QTableView 中丢失了有关父级的信息” 这没有多大意义。该视图不应该为您提供信息。该信息来自您正在代理的源模型。制作代理时,忘记视图 - 模型不关心视图,它们必须在没有附加视图的情况下工作!我对您的问题到底是什么感到有些不知所措:这根本不难做到。请发布一些代码,否则如果没有人为你做这一切,这将无法解决。
-
在任何情况下,您都不需要做任何特别的事情来显示一棵树“好像”它是一张桌子。只需告诉树视图将自身展平(查找)。从字面上看是一行代码,尽管表格格式与您显示的不完全一样 - 它只是一棵扁平的树。将所有三列都放在树中,然后在显示为树时隐藏其中一列,或者在显示为伪表时全部显示。
-
看看this answer 是否有用:它至少可以满足您的部分需求。
-
我第一部分的措辞是错误的——我的意思是如果我使用代理模型来展平我的标准模型,我会丢失信息。但我喜欢把树弄平的想法——不知道这是可能的!不幸的是,我在 Python 中找不到任何具有二维子级的树的示例。
标签: python qt pyside2 qtableview qtreeview