PyQt:如何在排序后保持 QTreeView 节点正确展开
我正在使用 QTreeModel 和 QTreeView 编写一个简单的测试程序,以便稍后进行更复杂的项目。在这个简单的程序中,我将数据分组,这些数据可以收缩或扩展,正如人们在 QTreeView 中所期望的那样。数据还可以按各种数据列排序(QTreeView.setSortingEnabled 为 True)。每个树项都是一个数据列表,因此 TreeModel 类中实现的排序函数使用内置的 python 列表排序:
self.layoutAboutToBeChanged.emit()
self.rootItem.childItems.sort(key=lambda x: x.itemData[col], reverse=order)
for item in self.rootItem.childItems:
item.childItems.sort(key=lambda x: x.itemData[col], reverse=order)
self.layoutChanged.emit()
问题是,每当我更改根的子项的排序时(树只有 2 层深,所以这是唯一有子级的级别)节点不一定像以前那样扩展。如果我在不展开或折叠任何内容的情况下将排序更改回来,则节点将像排序更改之前一样展开。
谁能向我解释我做错了什么?我怀疑这是没有正确地重新分配 QModelIndex 与排序节点的问题,但我不确定。
I'm writing a simple test program using QTreeModel and QTreeView for a more complex project later on. In this simple program, I have data in groups which may be contracted or expanded, as one would expect in a QTreeView. The data may also be sorted by the various data columns (QTreeView.setSortingEnabled is True). Each tree item is a list of data, so the sort function implemented in the TreeModel class uses the built-in python list sort:
self.layoutAboutToBeChanged.emit()
self.rootItem.childItems.sort(key=lambda x: x.itemData[col], reverse=order)
for item in self.rootItem.childItems:
item.childItems.sort(key=lambda x: x.itemData[col], reverse=order)
self.layoutChanged.emit()
The problem is that whenever I change the sorting of the root's child items (the tree is only 2 levels deep, so this is the only level with children) the nodes aren't necessarily expanded as they were before. If I change the sorting back without expanding or collapsing anything, the nodes are expanded as before the sorting change.
Can anyone explain to me what I'm doing wrong? I suspect it's something with not properly reassigning QModelIndex with the sorted nodes, but I'm not sure.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为了回答你的问题“我做错了什么”——你在发出layoutChanged()之前没有更新持久模型索引。模型的客户端不会神奇地知道模型的数据是如何移动的;例如,他们不知道索引 (2,0,root) 已变为 (12,0,root)。
传达更改的方式是发出布局信号;你那部分是正确的。 Qt 最有可能通过将其保留的任何 QModelIndexes 转换为 QPersistentModelIndex 来响应 layoutAboutToBeChanged()。当它获取layoutChanged()时,它会将它们转换回来。在这之间,您应该查看 QPersistentModelIndex 列表并使用新位置更新索引。检查文档中的layoutChanged() 信号。
To answer your question "what I'm doing wrong" -- you didn't update the persistent model indexes before emitting layoutChanged(). The clients of your model don't magically know how your model's data has moved; for example, they don't know that the index (2,0,root) moved to become (12,0,root).
The way you communicate the change is by emitting the layout signals; you have that part correct. Qt most likely responds to layoutAboutToBeChanged() by converting any QModelIndexes it keeps into QPersistentModelIndex. When it gets layoutChanged() it converts them back. In-between, you're supposed to look through that QPersistentModelIndex list and update the indexes with new locations. Check the docs for the layoutChanged() signal.
我通过实现 QSortFilterProxyModel 进行排序解决了这个问题。
I solved the problem by implementing a QSortFilterProxyModel for the sort.