PyQt5 QTreeView无法展开孙级节点问题求助
PyQt树形视图展开/折叠功能修复方案
问题分析
你的代码存在两个核心问题导致子节点无法展开:
- 方法调用笔误:MainWindow中调用了不存在的
add_group方法,实际模型中定义的是add_items,导致数据未正确加载(若你本地代码是笔误则忽略,但需确保调用正确)。 - 树形结构构建错误:不同层级的节点被分散到不同列中,导致点击子节点列(如Variant、Colour)时,对应的索引节点没有挂载子节点,无法触发展开/折叠;同时点击事件未处理跨列点击的情况。
修复步骤及代码
1. 修正方法调用笔误
将MainWindow中的model.add_group(key, item)改为model.add_items(key, item)。
2. 调整树形结构构建逻辑
把每个层级的节点作为整行添加到父节点下,确保子节点正确挂载到父节点的行结构中。
3. 优化点击事件处理
确保点击任意列都能触发对应行第一列节点的展开/折叠。
以下是修复后的完整代码:
from PyQt5 import QtCore, QtGui, QtWidgets class GroupView(QtWidgets.QTreeView): def __init__(self, model, parent=None): super(GroupView, self).__init__(parent) self.setIndentation(20) # 恢复缩进,方便区分层级 self.clicked.connect(self.on_clicked) self.setModel(model) self.header().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents) @QtCore.pyqtSlot(QtCore.QModelIndex) def on_clicked(self, index): # 获取当前行第一列的索引,确保点击任意列都操作行的根节点 first_col_index = index.sibling(index.row(), 0) self.setExpanded(first_col_index, not self.isExpanded(first_col_index)) class GroupModel(QtGui.QStandardItemModel): def __init__(self, parent=None): super(GroupModel, self).__init__(parent) self.setColumnCount(5) self.setHorizontalHeaderLabels(["Name", "Variant", "Colour", "Size", "Stock"]) def add_items(self, key, item): root_item = self.invisibleRootItem() root_item.setEditable(False) # 构建根节点行(产品名称层级) root_row = [ QtGui.QStandardItem(key), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(str(item['total'])) ] for cell in root_row: cell.setEditable(False) root_item.appendRow(root_row) product_item = root_row[0] # 添加Variant层级 for key1, item1 in item['var'].items(): variant_row = [ QtGui.QStandardItem(), QtGui.QStandardItem(key1), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(str(item1['total'])) ] for cell in variant_row: cell.setEditable(False) product_item.appendRow(variant_row) variant_item = variant_row[1] # 添加Colour层级 for key2, item2 in item1['colour'].items(): colour_row = [ QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(key2), QtGui.QStandardItem(), QtGui.QStandardItem(str(item2['total'])) ] for cell in colour_row: cell.setEditable(False) variant_item.appendRow(colour_row) colour_item = colour_row[2] # 添加Size层级 for key3, item3 in item2['size'].items(): size_row = [ QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(), QtGui.QStandardItem(key3), QtGui.QStandardItem(str(item3)) ] for cell in size_row: cell.setEditable(False) colour_item.appendRow(size_row) class MainWindow(QtWidgets.QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) model = GroupModel(self) tree_view = GroupView(model) self.setCentralWidget(tree_view) product_dict = { 'T-Shirt Minion': { 'total': 510, 'var': { 'Lengan Panjang': { 'total': 370, 'colour': { 'Merah': { 'total': 370, 'size': {'S': 100, 'L': 170, 'M': 100} } } }, 'Lengan Pendek': { 'total': 140, 'colour': {'Merah': {'total': 140, 'size': {}}} } } } } for key, item in product_dict.items(): model.add_items(key, item) if __name__ == '__main__': import sys app = QtWidgets.QApplication(sys.argv) w = MainWindow() w.resize(720, 400) w.show() sys.exit(app.exec_())
修复说明
- 调整了树形结构的构建方式,每个层级的节点作为整行添加到父节点下,确保子节点正确挂载。
- 修改点击事件,点击任意列都会触发对应行第一列节点的展开/折叠,符合Excel数据透视表的操作习惯。
- 恢复了树形视图的缩进,让层级关系更清晰。
内容的提问来源于stack exchange,提问作者Anthony Lauly
相关产品推荐
相关产品推荐

