树控件可以为用户显示节点层次结构,而每个节点又可以包含子节点,包含子节点的节点叫父节点,在设计树形结构(如导航菜单等)时,非常方便。PyQt5中提供了两个树控件,分别为TreeView和TreeWidget,本节将对它们的使用进行详解。
1 TreeView:树视图
TreeView控件对应PyQt5中的QTreeView类,它是树控件的基类,在使用时必须为其提供一个模型来与之配合。
QTreeView类的常用方法及说明如表所示。
| 方 法 | 说 明 |
|---|---|
| autoExpandDelay() | 获取自动展开节点所需的延时时间 |
| collapse() | 收缩指定级的节点 |
| collapseAll() | 收缩所有节点 |
| expand() | 展开指定级的节点 |
| expandAll() | 展开所有节点 |
| header() | 树的头信息,常用的有一个setVisible()方法,用来设置是否显示头 |
| isHeaderHidder() | 判断是否隐藏头部 |
| setAutoExpandDelay() | 设置自动展开的延时时间,单位为毫秒,如果值小于0,表示禁用自动展开 |
| setAlternatingRowColors() | 设置每间隔一行颜色是否一样 |
| setExpanded() | 根据索引设置是否展开节点 |
| setHeaderHidden() | 设置是否隐藏头部 |
| setItemsExpandable() | 设置项是否展开 |
| setModel() | 设置要显示的数据模型 |
| setSortingEnabled() | 设置单击头部时是否可以排序 |
| setVerticalScrollBarPolicy() | 设置是否显示垂直滚动条 |
| setHorizontalScrollBarPolicy() | 设置是否显示水平滚动条 |
| setEditTriggers() | 设置默认的编辑触发器 |
| setExpandsOnDoubleClick() | 设置是否支持双击展开树节点 |
| setWordWrap() | 设置自动换行 |
| selectionModel() | 获取选中的模型 |
| sortByColumn() | 根据列排序 |
| setSelectionMode() | 设置选中模式,取值如下: ◆ QAbstractItemView.NoSelection:不能选择 ◆ QAbstractItemView.SingleSelection:单选 ◆ QAbstractItemView.MultiSelection:多选 ◆ QAbstractItemView.ExtendedSelection:正常单选,按下 ◆ QAbstractItemView.ContiguousSelection:与ExtendedSelection类似 |
| setSelectionBehavior() | 设置选中方式,取值如下: ◆ QAbstractItemView.SelectItems:选中当前项 ◆ QAbstractItemView.SelectRows:选中整行 ◆ QAbstractItemView.SelectColumns:选中整列 |
下面分别介绍如何使用TreeView控件分层显示PyQt5内置模型的数据和自定义的数据。
1)使用内置模型中的数据
PyQt5中提供的内置模型及说明如表所示。
| 模 型 | 说 明 |
|---|---|
| QStringListModel | 存储简单的字符串列表 |
| QStandardItemModel | 可以用于树结构的存储,提供了层次数据 |
| QFileSystemModel | 存储本地系统的文件和目录信息(针对当前项目) |
| QDirModel | 存储文件系统 |
| QSqlQueryModel | 存储SQL中的查询结构集 |
| QSqlTableModel | 存储SQL中的表格数据 |
| QSqlRelationalTableModel | 存储有外键关系的SQL表格数据 |
| QSortFilterProxyModel | 对模型中的数据进行排序或者过滤 |
实例 在TreeView中显示系统文件目录
使用系统内置的QDirModel作为数据模型,在TreeView中显示系统的文件目录,代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(469, 280)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.treeView = QtWidgets.QTreeView(self.centralwidget) # 创建树对象
self.treeView.setGeometry(QtCore.QRect(0, 0, 471, 281)) # 设置坐标位置和大小
# 设置垂直滚动条为按需显示
self.treeView.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
# 设置水平滚动条为按需显示
self.treeView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
# 设置双击或者按下回车键时,使树节点可编辑
self.treeView.setEditTriggers(QtWidgets.QAbstractItemView.DoubleClicked|QtWidgets.QAbstractItemView.EditKeyPressed)
# 设置树节点为单选
self.treeView.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
# 设置选中节点时为整行选中
self.treeView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.treeView.setAutoExpandDelay(-1) # 设置自动展开的延时为-1,表示自动展开不可用
self.treeView.setItemsExpandable(True) # 设置是否可以展开项
self.treeView.setSortingEnabled(True) # 设置单击头部可排序
self.treeView.setWordWrap(True) # 设置自动换行
self.treeView.setHeaderHidden(False) # 设置不隐藏头部
self.treeView.setExpandsOnDoubleClick(True) # 设置双击可以展开节点
self.treeView.setObjectName("treeView")
self.treeView.header().setVisible(True) # 设置显示头部
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
model =QtWidgets.QDirModel() # 创建存储文件系统的模型
self.treeView.setModel(model) # 为树控件设置数据模型
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
import sys
# 程序入口,程序从此处启动PyQt设计的窗体
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow() # 创建窗体对象
ui = Ui_MainWindow() # 创建PyQt设计的窗体对象
ui.setupUi(MainWindow) # 调用PyQt窗体的方法对窗体对象进行初始化设置
MainWindow.show() # 显示窗体
sys.exit(app.exec_()) # 程序关闭时退出进程
运行程序,效果如图所示。

2)使用自定义数据
PyQt5中提供了一个QStandardItemModel模型,该模型可以存储任意层次结构的数据,本节将介绍如何使用QStandardItemModel模型存储数据,并显示在TreeView控件中。
实例 使用TreeView显示各个班级的学生成绩信息
创建一个PyQt5窗口,并在其中添加一个TreeView控件,然后在.py文件中使用QStandardItemModel模型存储某年级下的各个班级的学生成绩信息,最后将设置完的QStandardItemModel模型作为TreeView控件的数据模型进行显示。代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(422, 197)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# 创建一个TreeView树视图
self.treeView = QtWidgets.QTreeView(self.centralwidget)
self.treeView.setGeometry(QtCore.QRect(0, 0, 421, 201))
self.treeView.setObjectName("treeView")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
model = QtGui.QStandardItemModel() # 创建数据模型
model.setHorizontalHeaderLabels(['年级','班级','姓名','分数'])
# 姓名列表
name=['马云','马化腾','李彦宏','王兴','刘强东','董明珠','张一鸣','任正非','丁磊','程维']
score=[65,89,45,68,90,100,99,76,85,73] # 分数列表
import random
# 设置数据
for i in range(0,6):
# 一级节点:年级,只设第1列的数据
grade = QtGui.QStandardItem(("%s年级")%(i + 1))
model.appendRow(grade) # 一级节点
for j in range(0,4):
# 二级节点:班级、姓名、分数
itemClass = QtGui.QStandardItem(("%s班")%(j+1))
itemName = QtGui.QStandardItem(name[random.randrange(10)])
itemScore = QtGui.QStandardItem(str(score[random.randrange(10)]))
# 将二级节点添加到一级节点上
grade.appendRow([QtGui.QStandardItem(""),itemClass,itemName,itemScore])
self.treeView.setModel(model) # 为TreeVIew设置数据模型
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
import sys
# 程序入口,程序从此处启动PyQt设计的窗体
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow() # 创建窗体对象
ui = Ui_MainWindow() # 创建PyQt设计的窗体对象
ui.setupUi(MainWindow) # 调用PyQt窗体的方法对窗体对象进行初始化设置
MainWindow.show() # 显示窗体
sys.exit(app.exec_()) # 程序关闭时退出进程
运行程序,展开年级节点,效果如图所示。

2 TreeWidget:树控件
TreeWidget树控件对应PyQt5中的QTreeWidget类,它提供了一个使用预定义树模型的树视图,它的每一个树节点都是一个QTreeWidgetItem。
由于QTreeWidget类继承自QTreeView,因此它具有QTreeView的所有公共方法。另外,它还提供了一些自身特有的方法,如表所示。
| 方 法 | 说 明 |
|---|---|
| addTopLevelItem() | 添加顶级节点 |
| insertTopLevelItems() | 在树的顶层索引中插入节点 |
| invisibleRootItem() | 获取树控件中不可见的根选项 |
| setColumnCount() | 设置要显示的列数 |
| setColumnWidth() | 设置列的宽度 |
| selectedItems() | 获取选中的树节点 |
QTreeWidgetItem类表示QTreeWidget中的树节点项,该类的常用方法如表所示。
| 方 法 | 说 明 |
|---|---|
| addChild() | 添加子节点 |
| setText() | 设置节点的文本 |
| setCheckState() | 设置指定节点的选中状态,取值如下: ◆ Qt.Checked:节点选中 ◆ Qt.Unchecked:节点未选中 |
| setIcon() | 为节点设置图标 |
| text() | 获取节点的文本 |
下面对TreeWidget控件的常见用法进行讲解。
1)使用TreeWidget控件显示树结构
使用TreeWidget控件显示树结构主要用到QTreeWidgetItem类,该类表示标准树节点,通过其setText()方法可以设置树节点的文本。
实例 使用TreeWidget控件显示树结构
创建一个PyQt5窗口,并在其中添加一个TreeWidget控件,然后保存为.ui文件,并使用Pyuic工具将其转换为.py文件,在.py文件中,通过创建QTreeWidgetItem对象为树控件设置树节点。代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QTreeWidgetItem
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(240, 150)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.treeWidget = QtWidgets.QTreeWidget(self.centralwidget)
self.treeWidget.setGeometry(QtCore.QRect(0, 0, 240, 150))
self.treeWidget.setObjectName("treeWidget")
self.treeWidget.setColumnCount(2) # 设置树结构中的列数
self.treeWidget.setHeaderLabels(['姓名', '职务']) # 设置列标题名
root = QTreeWidgetItem(self.treeWidget) # 创建节点
root.setText(0, '组织结构') # 设置顶级节点文本
# 定义字典,存储树结构中显示的数据
dict = {'任正非': '华为董事长', '马云': '阿里巴巴创始人', '马化腾': '腾讯CEO', '李彦宏': '百度CEO',
'董明珠': '格力董事长'}
for key, value in dict.items(): # 遍历字典
child = QTreeWidgetItem(root) # 创建子节点
child.setText(0, key) # 设置第一列的值
child.setText(1, value) # 设置第二列的值
self.treeWidget.addTopLevelItem(root) # 将创建的树节点添加到树控件中
self.treeWidget.expandAll() # 展开所有树节点
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
import sys
# 程序入口,程序从此处启动PyQt设计的窗体
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow() # 创建窗体对象
ui = Ui_MainWindow() # 创建PyQt设计的窗体对象
ui.setupUi(MainWindow) # 调用PyQt窗体的方法对窗体对象进行初始化设置
MainWindow.show() # 显示窗体
sys.exit(app.exec_()) # 程序关闭时退出进程
运行程序,效果如图所示。

2)为节点设置图标
为节点设置图标主要用到了QTreeWidgetItem类的setIcon()方法。例如,为上述实例中的第一列的每个企业家姓名前面设置其对应公司的图标,代码如下:
# 为节点设置图标
if key == '任正非':
child.setIcon(0, QtGui.QIcon('图标/01.png'))
elif key == '马云':
child.setIcon(0, QtGui.QIcon('图标/02.png'))
elif key == '马化腾':
child.setIcon(0, QtGui.QIcon('图标/03.png'))
elif key == '李彦宏':
child.setIcon(0, QtGui.QIcon('图标/04.png'))
elif key == '董明珠':
child.setIcon(0, QtGui.QIcon('图标/05.png'))
Info: 说明 上面代码中用到了5张图片,需要在
.py文件的同级目录中创建图标文件夹,并将用到的5张图片提前放到该文件夹中。
运行程序,效果如图所示。

3)为节点设置复选框
为节点设置复选框主要用到了QTreeWidgetItem类中的setCheckState()方法,该方法中可以设置选中(Qt.Checked),也可以设置未选中(Qt.Unchecked)。例如,为上述实例中的第一列设置复选框,并全部设置为选中状态,代码如下:
# 为节点设置复选框,并且选中
child.setCheckState(0, QtCore.Qt.Checked)
运行程序,效果如图所示。

4)设置隔行变色显示树节点
隔行变色显示树节点需要用到TreeWidget控件的setAlternatingRowColors()方法,设置为True,表示隔行换色;设置为False,表示统一颜色。例如,将上述实例中的树节点设置为隔行变色形式显示,代码如下:
self.treeWidget.setAlternatingRowColors(True) # 设置隔行变色
运行程序,效果如图所示,从图可以看出,树控件的奇数行为浅灰色背景,而偶数行为白色背景。

5)获取选中节点的文本
在获取选中节点的文本时,首先需要使用currentItem()方法获取当前的选中项,然后通过text()方法获取指定列的文本。例如,在单击上述实例中的树节点时,定义一个槽函数,用来显示单击的树节点文本,代码如下:
def gettreetext(self, index):
item = self.treeWidget.currentItem() # 获取当前选中项
# 弹出提示框,显示选中项的文本
QtWidgets.QMessageBox.information(MainWindow, '提示', '您选择的是:%s -- %s' % (item.text(0), item.text(1)),QtWidgets.QMessageBox.Ok)
为树控件的clicked信号绑定自定义的槽函数,以便在单击树控件时发射,代码如下:
# 为树控件绑定单击信号
self.treeWidget.clicked.connect(self.gettreetext)
运行程序,单击树中的节点,即可弹出提示框,显示单击的树节点的文本,如图所示。
