QTreeView的使用(一)

写作思路

1、简易QTreeView的使用(搞懂QTreeView Model 之间的关系)
2、QStyledItemDelegate + QAbstractListModel自定义Model(自定义Model的使用,以及自定义Model内部需要重构的方法的意义)

1、简易QTreeView的使用

import sys
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtWidgets import QMainWindow, QApplication, QTreeView


class Example(QMainWindow):

    def __init__(self):
        super().__init__()
        self.treeView = None
        self.initUI()

    def initUI(self):
        self.treeView = QTreeView()
        model = QStandardItemModel()
        for row in range(4):
            item = QStandardItem(str(row))
            model.appendRow(item)
        self.treeView.setModel(model)
        self.treeView.show()
        self.treeView.setWindowTitle("SimpleTree")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

运行结果如下
在这里插入图片描述
首先了解一下各个Model的继承关系(如下图)以及使用规则
在这里插入图片描述

参考的内容,包括使用解析
用法比较简单,QStandardItemModel可以使用QStandardItem,通过不断添加子节点,从而构建出list、table、tree结构的数据。

使用QStandardItemModel表示数据集具有以下优点:
实现代码简单,该类使用QStandardItem存放数据项,用户不必定义任何数据结构来存放数据项;
QStandardItem使用自关联关系,能够表达列表、表格、树甚至更复杂的数据结构,能够涵盖各种各样的数据集;
QStandardItem本身存放着多个『角色,数据子项』,视图类、委托类或者其他用户定义的类能够方便地依据角色访问各个数据子项。
缺点:
当数据集中的数据项很多时,施加在数据集上的某些操作的执行效率会很低。
数据太大时,占用内存巨大,性能低下

QTreeView中关于 row column parent的定义:
在这里插入图片描述
在获取不同的对象时如下:
A节点:QModelIndex indexA = model->index(0, 0, QModelIndex());
B节点:QModelIndex indexC = model->index(2, 1, QModelIndex());
C节点:QModelIndex indexB = model->index(1, 0, indexA);
这个东西先记者,以后你会用到的

2、QStyledItemDelegate + QAbstractListModel自定义Model

import sys 
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QApplication, QTreeView, QWidget, QPushButton, QVBoxLayout, QStyledItemDelegate


class Window(QWidget):
    changeStyleTriggered = pyqtSignal()

    def __init__(self): 
     super(Window, self).__init__()
     self.createTree()

    def createTree(self): 
     data = ['A', 'B', 'C', 'D', 'E', 'F'] 
     model = MyTreeView(data) 
     self.treeView = QTreeView()
     self.treeView.setItemDelegate(BoldDelegate())
     self.treeView.setModel(model) 
     layout = QVBoxLayout()
     layout.addWidget(self.treeView) 
     self.setStyleSheet("QTreeView::indicator:checked {image: url(door-closed-fill.svg)}"
                        "QTreeView::indicator:unchecked {image: url(door-open-fill.svg)}")
     self.setLayout(layout)

class TestItem(): 
    def __init__(self, name, checked): 
     self.checked = checked 
     self.name = name 

class BoldDelegate(QStyledItemDelegate):
    def paint(self, painter, option, index):
     option.font.setWeight(QFont.Bold)
     QStyledItemDelegate.paint(self, painter, option, index)

class MyTreeView(QAbstractListModel): 
    def __init__(self, args, parent=None): 
     super(MyTreeView, self).__init__(parent)

     self.args = [] 
     for item_name in args: 
      self.args.append(TestItem(item_name, False))

    def rowCount(self, parent): 
     return len(self.args) 

    def headerData(self, section, orientation, role): 
     if role == Qt.DisplayRole: 
      if orientation == Qt.Horizontal: 
       return "Nodes" 

    def flags(self, index): 
     return Qt.ItemIsUserCheckable | Qt.ItemIsEditable | Qt.ItemIsSelectable | Qt.ItemIsEnabled 

    def data(self, index, role=Qt.DisplayRole): 
     if role == Qt.DisplayRole: 
      row = index.row()
      return self.args[row].name 

     if role == Qt.CheckStateRole: 
      row = index.row()
      if self.args[row].checked == False: 
       return Qt.Unchecked 
      else: 
       return Qt.Checked 

    def setData(self, index, value, role): 
     if role == Qt.CheckStateRole: 
      row = index.row() 
      self.args[row].checked = not self.args[row].checked    
     return True 

def main(): 
    myapp = QApplication(sys.argv) 

    window = Window() 
    window.show() 
    myapp.exec_() 

if __name__ == '__main__': 
    main() 

上述代码效果如下图
在这里插入图片描述
先大体的解释一下上述的过程:
①创建一个继承自QAbstractListModel的对象
②将数据data设置给上述Model对象
③通过各自View的SetModel方法,将Model设置给View

接下来一一解释上面各个函数的作用:
①rowCount(self, parent):返回行数(关于行的定义在上面截屏),假如此时改成 return 2,那么将只显示 A B两个子节点
②headerData(self, section, orientation, role): 修改标题的数据,orientation就是方向,role在上一篇博文已经介绍过了触发事件及QTableView的使用
③flags(self, index):就是对每一个数据项能否做什么处理的一个标记,以Qt.ItemIsUserCheckable为例,如果此处删去Qt.ItemIsUserCheckable,那么上图gif中,那个门就不能控制了~再比如Qt.ItemIsSelectable,如果删去,那么就不可选中,具体效果可以自己去尝试
④data(self, index, role=Qt.DisplayRole):对应view中的数据要如何显示(在这里就是QTreeView),如何处理,比如Qt.DisplayRole,就是设置数据该如何显示的;Qt.CheckStateRole就是那个门(其实就是一个勾选框,只是我在
self.setStyleSheet(“QTreeView::indicator:checked {image: url(door-closed-fill.svg)}”
“QTreeView::indicator:unchecked {image: url(door-open-fill.svg)}”)
这段代码里面修改了表现形式,删去就可以看到标准形式
⑤setData(self, index, value, role): 当我们修改数据之后,数据要怎么变化,比如这里就是说当我们修改了勾选框猴,数据内的选中标志取反

补充一下:
①在上述代码中创建了一个BoldDelegate类,继承自 QStyledItemDelegate ,通过创建这个类对象,并通过调用对应View的 setItemDelegate(BoldDelegate()) 就能设置数据的格式
②上面有一个类TestItem,这个类相当于是对传入的数据做一个处理,让其变成我们想要的结构类型,这里数据较为简单,因此就相当于struct

自己去探索吧~

QAbstractListModel是继承自QAbstractItemModel,因此在QAbstractListModel中找不到的虚方法说明可以到QAbstractItemModel中去找

后面还有一篇更复杂的QTreeView博文,后面补

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值