Python代码
TreeModel.py
import PyQt5.Qt
import PyQt5.QtGui
from PyQt5.QtCore import QAbstractItemModel, QVariant, QModelIndex, Qt
class TreeItem:
def __init__(self, data, parent = None):
self.parentItem = parent # 父节点
self.childItems = [] # 子节点
self.itemData = data # 子节点对应数据
self._row = -1 # 此item位于父节点第几个
def appendChild(self, child):
child.setRow(len(self.childItems))
self.childItems.append(child)
def child(self, row):
return self.childItems[row]
def childCount(self):
return len(self.childItems)
def columnCount(self):
return len(self.itemData)
def data(self, column):
return self.itemData[column]
# 保存该节点是其父节点的第几个子节点,查询优化所用
def setRow(self, row: int):
self._row = row
# 返回本节点位于父节点下第几个子节点
def row(self):
return self._row
def parent(self):
return self.parentItem
class TreeModel(QAbstractItemModel):
def __init__(self, parent = None):
super(TreeModel, self).__init__()
self.rootItem = None # 最顶层根节点
self.updataData()
# 在parent节点下,第row行,第column列位置上创建索引
def data(self, index: QModelIndex, role: int = ...):
if not index.isValid():
return QVariant()
# 添加图标
if role == Qt.DecorationRole and index.column() == 0:
return PyQt5.QtGui.QIcon("images/snapshot.png")
# 显示节点数据值
if role == Qt.DisplayRole:
item = index.internalPointer()
return item.data(index.column())
return QVariant()
def flags(self, index: QModelIndex):
if not index.isValid():
return 0
return Qt.ItemIsEnabled | Qt.ItemIsSelectable
# 获取表头数据
def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> QVariant:
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self.rootItem.data(section)
return QVariant()
# 在parent节点下,第row行,第column列位置上创建索引
def index(self, row: int, column: int, parent: QModelIndex = ...) -> QModelIndex:
if not self.hasIndex(row, column, parent):
return QModelIndex()
if not parent.isValid():
parentItem = self.rootItem
else:
parentItem = parent.internalPointer()
childItem = parentItem.child(row)
if childItem:
return self.createIndex(row, column, childItem) # 展开树形,为子节点建立索引
else:
return QModelIndex()
# 创建index的父索引
def parent(self, index: QModelIndex) -> QModelIndex:
if not index.isValid():
return QModelIndex()
childItem = index.internalPointer()
parentItem = childItem.parent()
# 顶层节点,直接返回空索引
if parentItem == self.rootItem:
return QModelIndex()
# 为父节点建立索引
return self.createIndex(parentItem.row(), 0, parentItem)
# 获取索引parent下有多少行
def rowCount(self, parent: QModelIndex = ...) -> int:
if not parent.isValid():
parentItem = self.rootItem
else:
parentItem = parent.internalPointer()
return parentItem.childCount() # 返回父节点下子节点数目
# 返回索引parent下有多少列
def columnCount(self, parent: QModelIndex = ...) -> int:
return self.rootItem.columnCount()
# 构建模型数据
def setupModelData(self, parent):
for i in range(10):
datas = [f"设备-{i + 1}", f"类型-{i + 1}"]
# 主节点下挂两个子节点
primary = TreeItem(datas, parent)
parent.appendChild(primary)
for j in range(2):
ds = [f"子设备-{j + 1}", f"子类型-{j + 1}"]
primary.appendChild(TreeItem(ds, primary))
# 更新模型数据
def updataData(self):
# 废弃旧模型数据
if self.rootItem:
del self.rootItem
self.rootItem = None
rootData = ['Tag', 'Type']
self.rootItem = TreeItem(rootData)
self.setupModelData(self.rootItem)
测试
关键测试代码如下:
self.model = TreeModel()
self.treeView = QTreeView(self)
self.treeView.setModel(self.model)
结果
参考
[1] https://blog.csdn.net/specialsun/article/details/84437740
[2] https://blog.csdn.net/chenyijun/article/details/125564474