QTreeView结合QSortFilterProxyModel插入三级子项失败问题
问题根源分析
你的问题出在TreeItem类的childNumber()方法上,这个方法的逻辑完全写反了,导致TreeModel无法正确生成父节点的索引,当添加三级子项时,模型无法识别正确的层级关系,所以新插入的项无法显示。
看一下你原来的childNumber()代码:
def childNumber(self): if self.parentItem is None: return self.parentItem.childItems.index(self) return 0
这里有两个严重错误:
- 当
self.parentItem为None时(也就是根节点),你试图访问parentItem.childItems,这会直接抛出AttributeError,因为None没有childItems属性。 - 当当前项有父节点时,你错误地返回
0,而正确的逻辑应该是返回当前项在父节点的子列表中的位置索引。
修正方案
把TreeItem类中的childNumber()方法替换为以下正确实现:
def childNumber(self): if self.parentItem is not None: return self.parentItem.childItems.index(self) return 0
这个修正做了两件事:
- 当当前项有父节点时,正确获取它在父节点子列表中的位置,这样
TreeModel的parent()方法就能生成正确的父索引。 - 当当前项是根节点(parentItem为None)时,返回0,符合根节点的层级逻辑。
验证修正效果
按照你的测试步骤重新操作:
- 点击任意一级项
- 点击“Add row”按钮添加二级子项
- 点击新创建的二级项
- 再次点击“Add row”按钮
此时你会看到三级子项正常显示,完全符合预期结果。
完整修正后的TreeItem.py代码
class TreeItem(object): ind_column_name = 0 ind_column_id = 1 ind_column_parent_id = 2 key_name = "name" key_id = "id" key_parent_id = "parent" key_new_id = "new_item_id" def __init__(self, data, parent=None): self.parentItem = parent self.itemData = data self.childItems = [] def child(self, row): try: return self.childItems[row] except IndexError: return "" def childCount(self): return len(self.childItems) def childNumber(self): if self.parentItem is not None: return self.parentItem.childItems.index(self) return 0 def columnCount(self): return len(self.itemData) def data(self, column): if column != self.ind_column_id and column != self.ind_column_parent_id: return self.itemData[column] return None def id_data(self, column): if column == self.ind_column_id or column == self.ind_column_parent_id: return self.itemData[column] def insertChildren(self, position, count, columns): if position < 0 or position > len(self.childItems): return False for row in range(count): data = [None for v in range(columns)] item = TreeItem(data, self) self.childItems.insert(position, item) return True def insertColumns(self, position, columns): if position < 0 or position > len(self.itemData): return False for column in range(columns): self.itemData.insert(position, None) for child in self.childItems: child.insertColumns(position, columns) return True def parent(self): return self.parentItem def removeChildren(self, position, count): if position < 0 or position + count > len(self.childItems): return False for row in range(count): self.childItems.pop(position) return True def removeColumns(self, position, columns): if position < 0 or position + columns > len(self.itemData): return False for column in range(columns): self.itemData.pop(position) for child in self.childItems: child.removeColumns(position, columns) return True def setData(self, column, value): if column < 0 or column >= len(self.itemData): return False self.itemData[column] = value return True def to_json(self): parent_id = self.itemData[self.ind_column_parent_id] item_id = self.itemData[self.ind_column_id] json_data = dict() json_data[self.key_name] = self.itemData[self.ind_column_name] if parent_id is not None: json_data[self.key_parent_id] = parent_id if item_id is not None: json_data[self.key_id] = item_id return json_data
内容的提问来源于stack exchange,提问作者Sergey Maslov
相关产品推荐
相关产品推荐

