【PyQt5】QTreeView使用自定义Model

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)

结果

image-20221116221218293

参考

[1] https://blog.csdn.net/specialsun/article/details/84437740

[2] https://blog.csdn.net/chenyijun/article/details/125564474

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值