QTreeView&QTreeWidget
- 一、QTreeView
-
- [1.1 核心概念:Model/View 架构](#1.1 核心概念:Model/View 架构)
-
- [1. QStandardItemModel](#1. QStandardItemModel)
- [2. QStandardItem](#2. QStandardItem)
- [1.2 最简单的用法:`QStandardItemModel`](#1.2 最简单的用法:
QStandardItemModel
) - [1.3 常用功能与属性设置](#1.3 常用功能与属性设置)
-
- [1. 外观定制](#1. 外观定制)
- [2. 交互性设置](#2. 交互性设置)
- [3. 常用操作](#3. 常用操作)
- [1.4 进阶用法:使用自定义模型](#1.4 进阶用法:使用自定义模型)
- [1.5 右键菜单 (Context Menu)](#1.5 右键菜单 (Context Menu))
- [1.6 总结](#1.6 总结)
- 二、QTreeWidget
-
- [2.1 核心概念:`QTreeWidget` vs `QTreeView`](#2.1 核心概念:
QTreeWidget
vsQTreeView
) - [2.2 基本用法](#2.2 基本用法)
- [2.3 常用功能与属性设置](#2.3 常用功能与属性设置)
-
- [1. 外观定制](#1. 外观定制)
- [2. 交互性设置](#2. 交互性设置)
- [3. 常用操作](#3. 常用操作)
- [2.4 右键菜单 (Context Menu)](#2.4 右键菜单 (Context Menu))
- [2.5 总结:何时使用 `QTreeWidget` vs `QTreeView`](#2.5 总结:何时使用
QTreeWidget
vsQTreeView
)
- [2.1 核心概念:`QTreeWidget` vs `QTreeView`](#2.1 核心概念:
一、QTreeView
QTreeView
是 Qt 中用于显示层级数据(树状结构)的核心控件,功能非常强大和灵活。它通常与**模型(Model)**配合使用,遵循 Model/View 架构。
1.1 核心概念:Model/View 架构
在 Qt 中,QTreeView
是一个视图(View) ,它本身不存储任何数据。它的职责是显示由**模型(Model)**提供的数据。
- Model (模型) :负责存储数据,并提供标准接口(如
rowCount
,data
,setData
)让 View 可以访问和修改数据。 - View (视图):负责将 Model 中的数据以特定的视觉形式(如树形、表格、列表)呈现给用户。
- Delegate (代理):(可选)负责数据的编辑和自定义渲染。
这种分离使得数据管理和界面显示解耦,代码更清晰、更易于维护。
1. QStandardItemModel
QStandardItemModel
是 Qt 中最常用、最灵活的模型类之一,它属于 Model/View 架构的一部分。它与 QStandardItem
配合使用,可以轻松构建各种复杂的、可编辑的数据结构,如列表、表格和树
QStandardItemModel
是一个基于项(Item)的模型。它的数据由一个二维的 QStandardItem
表格构成。
- 模型 (Model) :
QStandardItemModel
本身。 - 项 (Item) :
QStandardItem
对象,它是数据的基本单位,每个项可以存储多种角色(Role)的数据(如显示文本、图标、工具提示等)。 - 索引 (Index) :
QModelIndex
对象,是访问模型中特定位置数据的"地址"。
核心成员函数
-
构造函数
QStandardItemModel(QObject *parent = nullptr)
: 创建一个空模型。QStandardItemModel(int rows, int columns, QObject *parent = nullptr)
: 创建一个具有指定行数和列数的空模型。
-
设置和获取数据
这些函数是
QStandardItemModel
的核心,用于操作模型中的QStandardItem
。-
QStandardItem *item(int row, int column = 0) const
:- 功能 : 获取指定行、列位置的
QStandardItem
指针。如果该位置没有项,则返回nullptr
。 - 示例 :
QStandardItem *myItem = model->item(0, 0);
- 功能 : 获取指定行、列位置的
-
void setItem(int row, int column, QStandardItem *item)
:- 功能 : 在指定的行、列位置设置一个
QStandardItem
。模型会接管该 item 的所有权 ,你不需要手动delete
它。 - 示例:
cppQStandardItem *newItem = new QStandardItem("Hello"); model->setItem(0, 0, newItem);
- 功能 : 在指定的行、列位置设置一个
-
QList<QStandardItem *> findItems(const QString &text, Qt::MatchFlags flags = Qt::MatchExactly, int column = 0) const
:- 功能 : 根据文本查找项。
flags
参数可以指定匹配方式(如Qt::MatchExactly
精确匹配,Qt::MatchContains
包含匹配)。 - 示例:
cppQList<QStandardItem*> foundItems = model->findItems("apple", Qt::MatchContains);
- 功能 : 根据文本查找项。
-
-
操作行和列
这些函数用于在模型中动态地添加或删除行和列。
-
bool insertRow(int row, const QList<QStandardItem *> &items)
:- 功能 : 在指定行
row
插入一行。items
列表中的项将填充新行的各个列。 - 示例:
cppQList<QStandardItem*> newRowItems; newRowItems << new QStandardItem("New Item 1") << new QStandardItem("New Item 2"); model->insertRow(model->rowCount(), newRowItems); // 在末尾插入一行
- 功能 : 在指定行
-
bool insertColumn(int column, const QList<QStandardItem *> &items)
:- 功能 : 在指定列
column
插入一列。items
列表中的项将填充新列的各个行。
- 功能 : 在指定列
-
void appendRow(const QList<QStandardItem *> &items)
:- 功能 : 在模型末尾添加一行。这是
insertRow(model->rowCount(), items)
的便捷版本。 - 示例 (添加顶层项):
cppQStandardItem *topLevelItem = new QStandardItem("顶层项"); model->appendRow(topLevelItem);
- 功能 : 在模型末尾添加一行。这是
-
bool removeRow(int row)
:- 功能 : 删除指定的行。该行上的所有
QStandardItem
都会被自动删除。
- 功能 : 删除指定的行。该行上的所有
-
bool removeColumn(int column)
:- 功能 : 删除指定的列。该列上的所有
QStandardItem
都会被自动删除。
- 功能 : 删除指定的列。该列上的所有
-
int rowCount(const QModelIndex &parent = QModelIndex()) const
:-
功能 : 返回指定父项
parent
下的行数。对于顶层项,parent
是QModelIndex()
。 -
int columnCount(const QModelIndex &parent = QModelIndex()) const
: -
功能 : 返回指定父项
parent
下的列数。
-
-
-
处理树状结构 (父项和子项)
QStandardItemModel
天生支持树状结构,通过QStandardItem
的appendRow()
方法可以轻松实现。-
QStandardItem *invisibleRootItem() const
:- 功能: 返回模型的一个不可见的根项。模型中的所有顶层项都是这个根项的子项。这在处理树状结构时非常有用,可以统一地对所有顶层项进行操作。
- 示例:
cppQStandardItem *root = model->invisibleRootItem(); QStandardItem *item1 = new QStandardItem("Item 1"); QStandardItem *item2 = new QStandardItem("Item 2"); root->appendRow(item1); root->appendRow(item2);
-
QModelIndex indexFromItem(const QStandardItem *item) const
:- 功能 : 根据一个
QStandardItem
指针获取其对应的QModelIndex
。这在需要将项的位置传递给视图时非常有用。
- 功能 : 根据一个
-
QStandardItem *itemFromIndex(const QModelIndex &index) const
:- 功能 : 根据一个
QModelIndex
获取其对应的QStandardItem
指针。这是item()
函数的另一种形式。
- 功能 : 根据一个
-
-
其他常用函数
-
void setHorizontalHeaderLabels(const QStringList &labels)
:- 功能: 设置水平标题栏的标签。
- 示例 :
model->setHorizontalHeaderLabels(QStringList() << "Name" << "Age");
-
void clear()
:- 功能: 清除模型中的所有数据和项,将模型重置为空状态。
-
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder)
:- 功能: 根据指定的列对模型数据进行排序。
-
QStandardItem
的关键函数
QStandardItemModel
的强大之处在于 QStandardItem
,以下是 QStandardItem
的一些关键函数:
QStandardItem(const QString &text, int type = Type)
: 构造函数,创建一个带有文本的项。void setText(const QString &text)
: 设置项的显示文本。QString text() const
: 获取项的显示文本。void setData(const QVariant &value, int role = Qt::UserRole + 1)
: 设置项的特定角色(Role)的数据。角色是QStandardItem
最强大的特性之一。Qt::DisplayRole
: 显示文本 (QString
)。Qt::DecorationRole
: 图标 (QIcon
)。Qt::ToolTipRole
: 工具提示 (QString
)。Qt::UserRole
: 自定义数据的起点。- 示例 :
item->setData(42, Qt::UserRole); // 存储一个自定义的整数值
QVariant data(int role = Qt::UserRole + 1) const
: 获取项的特定角色的数据。- 示例 :
int value = item->data(Qt::UserRole).toInt();
- 示例 :
void appendRow(QStandardItem *item)
: 向当前项添加一个子项。这是构建树状结构的核心。-
示例 :
cppQStandardItem *parentItem = model->item(0); QStandardItem *childItem = new QStandardItem("Child"); parentItem->appendRow(childItem);
-
总结
QStandardItemModel
是一个功能强大且易于使用的模型类。
- 核心 : 由
QStandardItem
对象组成的二维表格。 - 强项 :
- 简单直观 : API 设计友好,比直接继承
QAbstractItemModel
简单得多。 - 功能全面: 同时支持列表、表格和树状结构。
- 数据丰富 : 通过
QStandardItem
的setData()
和data()
方法,可以为每个单元格存储多种角色的数据。
- 简单直观 : API 设计友好,比直接继承
- 适用场景 : 当你需要一个灵活的数据容器,并且数据量不是特别巨大(例如,几千到几万行以内)时,
QStandardItemModel
是你的首选。对于超大规模数据或需要高度优化性能的场景,才考虑创建自定义模型。
2. QStandardItem
QStandardItem
是 Qt 中 QStandardItemModel
的核心组成部分,用于存储模型中的单个数据项。它提供了丰富的函数来管理数据、状态和子项,是构建树形、列表或表格结构的基础。
构造函数
函数 | 说明 |
---|---|
QStandardItem(int type = Type) |
创建一个空项,type 用于自定义项类型(默认值为 Type )。 |
QStandardItem(const QString &text, int type = Type) |
创建一个包含指定文本的项。 |
QStandardItem(const QIcon &icon, const QString &text, int type = Type) |
创建一个包含图标和文本的项。 |
数据访问与设置(核心功能)
QStandardItem
可以存储多种角色(Role
)的数据(如显示文本、图标、工具提示等),通过以下函数操作:
函数 | 说明 |
---|---|
QVariant data(int role = Qt::UserRole + 1) const |
获取指定角色的数据(返回 QVariant ,需转换为具体类型)。 |
void setData(const QVariant &value, int role = Qt::UserRole + 1) |
设置指定角色的数据。 |
QString text() const |
获取 Qt::DisplayRole 角色的文本(等价于 data(Qt::DisplayRole).toString() )。 |
void setText(const QString &text) |
设置 Qt::DisplayRole 角色的文本(等价于 setData(text, Qt::DisplayRole) )。 |
QIcon icon() const |
获取 Qt::DecorationRole 角色的图标。 |
void setIcon(const QIcon &icon) |
设置 Qt::DecorationRole 角色的图标。 |
复选框相关
函数 | 说明 |
---|---|
Qt::CheckState checkState() const |
获取复选状态(Qt::Unchecked /Qt::Checked /Qt::PartiallyChecked )。 |
void setCheckState(Qt::CheckState state) |
设置复选状态(需先启用复选框)。 |
bool isCheckable() const |
判断项是否可勾选(是否设置了 Qt::ItemIsUserCheckable 标志)。 |
void setCheckable(bool checkable) |
设置项是否可勾选(本质是修改 flags 中的 Qt::ItemIsUserCheckable 标志)。 |
项的状态与行为(flags)
flags
用于控制项的交互行为(如是否可选中、编辑、勾选等),通过以下函数操作:
函数 | 说明 |
---|---|
Qt::ItemFlags flags() const |
获取项的当前行为标志。 |
void setFlags(Qt::ItemFlags flags) |
设置项的行为标志(常用标志见下表)。 |
常用 Qt::ItemFlags
标志:
Qt::ItemIsSelectable
:项可被选中。Qt::ItemIsEditable
:项可被编辑。Qt::ItemIsUserCheckable
:项可被勾选(显示复选框)。Qt::ItemIsEnabled
:项可交互(否则为灰色不可用状态)。
示例:设置项可勾选但不可编辑:
cpp
item->setFlags(item->flags() | Qt::ItemIsUserCheckable
& ~Qt::ItemIsEditable);
子项管理(树形结构)
QStandardItem
支持嵌套子项,用于构建树形结构:
函数 | 说明 |
---|---|
void appendRow(QStandardItem *child) |
向当前项添加一个子项(作为最后一行)。 |
void appendRow(const QList<QStandardItem *> &items) |
向当前项添加一行子项(多列场景)。 |
void insertRow(int row, QStandardItem *child) |
在指定行插入一个子项。 |
QStandardItem *child(int row, int column = 0) const |
获取指定行、列的子项(默认第 0 列)。 |
int rowCount() const |
返回当前项的子项行数。 |
int columnCount() const |
返回当前项的子项列数。 |
void removeRow(int row) |
删除指定行的子项。 |
bool hasChildren() const |
判断当前项是否有子项。 |
父项与位置信息
函数 | 说明 |
---|---|
QStandardItem *parent() const |
获取当前项的父项(顶层项返回 nullptr )。 |
int row() const |
返回当前项在父项中的行索引。 |
int column() const |
返回当前项在父项中的列索引。 |
其他常用函数
函数 | 说明 |
---|---|
void setToolTip(const QString &text) |
设置鼠标悬停时的工具提示(Qt::ToolTipRole )。 |
QString toolTip() const |
获取工具提示文本。 |
void setWhatsThis(const QString &text) |
设置 What's This 帮助文本(Qt::WhatsThisRole )。 |
bool isEnabled() const |
判断项是否可用(Qt::ItemIsEnabled 标志是否设置)。 |
void setEnabled(bool enabled) |
设置项是否可用(修改 Qt::ItemIsEnabled 标志)。 |
综合使用
cpp
// 创建一个带图标和文本的项
QStandardItem *item = new QStandardItem(QIcon("icon.png"), "示例项");
// 设置复选框并初始化为未勾选
item->setCheckable(true);
item->setCheckState(Qt::Unchecked);
// 设置工具提示
item->setToolTip("这是一个示例项");
// 添加子项
QStandardItem *child = new QStandardItem("子项");
item->appendRow(child);
// 获取子项并修改其文本
QStandardItem *firstChild = item->child(0);
if (firstChild) {
firstChild->setText("修改后的子项");
}
总结
QStandardItem
是 QStandardItemModel
的基础单元,其核心功能包括:
- 通过
data()
/setData()
管理多角色数据(文本、图标等)。 - 通过
checkState()
/setCheckState()
处理复选框状态。 - 通过
appendRow()
/child()
管理子项,构建树形结构。 - 通过
flags()
控制项的交互行为(可选中、编辑等)。
掌握这些函数可以灵活处理 QTreeView
、QListView
等视图中的数据展示和交互。
1.2 最简单的用法:QStandardItemModel
对于大多数简单到中等复杂度的应用,QStandardItemModel
是首选。它是一个灵活的、可以存储 QStandardItem
对象的通用模型。
步骤:
- 创建
QTreeView
和QStandardItemModel
。 - 使用
QStandardItem
创建数据项。 - 通过
model->appendRow()
和parentItem->appendRow()
添加顶层项和子项。 - 将 Model 设置到 View 上 (
treeView->setModel(model)
)。
代码示例:
cpp
#include <QApplication>
#include <QMainWindow>
#include <QTreeView>
#include <QStandardItemModel>
#include <QStandardItem>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow mainWindow;
mainWindow.setWindowTitle("QTreeView 基础示例");
// 1. 创建视图和模型
QTreeView *treeView = new QTreeView(&mainWindow);
QStandardItemModel *model = new QStandardItemModel(&mainWindow);
model->setHeaderData(0, Qt::Horizontal, "项目"); // 设置列标题
// 2. 创建根节点 (模型本身就是一个不可见的根)
QStandardItem *rootItem = model->invisibleRootItem();
// 3. 创建顶层项 "动物" 及其子项
QStandardItem *animalItem = new QStandardItem("动物");
QStandardItem *dogItem = new QStandardItem("狗");
QStandardItem *catItem = new QStandardItem("猫");
animalItem->appendRow(dogItem);
animalItem->appendRow(catItem);
rootItem->appendRow(animalItem);
// 4. 创建顶层项 "植物" 及其子项
QStandardItem *plantItem = new QStandardItem("植物");
QStandardItem *flowerItem = new QStandardItem("花");
QStandardItem *treeItem = new QStandardItem("树");
plantItem->appendRow(flowerItem);
plantItem->appendRow(treeItem);
rootItem->appendRow(plantItem);
// 5. 将模型设置到视图
treeView->setModel(model);
// 6. 自动展开所有节点
treeView->expandAll();
mainWindow.setCentralWidget(treeView);
mainWindow.resize(400, 300);
mainWindow.show();
return a.exec();
}
1.3 常用功能与属性设置
QTreeView
提供了大量函数来定制其外观和行为。
1. 外观定制
-
setHeaderHidden(bool hidden)
: 隐藏或显示标题栏。cpptreeView->setHeaderHidden(true);
-
setIndentation(int i)
: 设置子项相对于父项的缩进像素。cpptreeView->setIndentation(20);
-
setRootIsDecorated(bool show)
: 设置是否显示根节点的展开/折叠图标。对于只有一个顶层项的树,通常设为false
。cpptreeView->setRootIsDecorated(false);
2. 交互性设置
-
setEditTriggers(EditTriggers triggers)
: 设置触发编辑的方式。cpp// 设置为双击或按 F2 时可编辑 treeView->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
-
setSelectionMode(SelectionMode mode)
: 设置选择模式(单选、多选等)。cpp// 允许选择多个项 treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
-
setSelectionBehavior(SelectionBehavior behavior)
: 设置选择行为(选择整行、整列或单个单元格)。cpp// 点击时选择整行 treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
3. 常用操作
-
获取当前选中项 :
cpp// 获取当前选中的顶层项 QModelIndex currentIndex = treeView->currentIndex(); if (currentIndex.isValid()) { QString text = currentIndex.data(Qt::DisplayRole).toString(); qDebug() << "当前选中项:" << text; }
-
展开/折叠所有节点 :
cpptreeView->expandAll(); treeView->collapseAll();
-
信号与槽 :
QTreeView
继承自QAbstractItemView
,提供了丰富的信号,如clicked
,doubleClicked
,pressed
,activated
等。cppconnect(treeView, &QTreeView::clicked, [](const QModelIndex &index) { QString text = index.data(Qt::DisplayRole).toString(); qDebug() << "点击了项:" << text; });
1.4 进阶用法:使用自定义模型
当你的数据结构非常复杂,或者需要更好的性能和控制时(例如,数据量巨大,或数据来自数据库),你应该创建自己的模型。
你需要继承 QAbstractItemModel
并必须重写以下纯虚函数:
rowCount(const QModelIndex &parent)
: 返回指定父项下的行数。columnCount(const QModelIndex &parent)
: 返回指定父项下的列数。data(const QModelIndex &index, int role)
: 返回指定索引和角色的数据。index(int row, int column, const QModelIndex &parent)
: 创建并返回一个索引。parent(const QModelIndex &index)
: 返回指定索引的父索引。
这部分比较复杂,但提供了无与伦比的灵活性。
1.5 右键菜单 (Context Menu)
为 QTreeView
添加右键菜单是非常常见的需求。
步骤:
- 在构造函数中设置
treeView->setContextMenuPolicy(Qt::CustomContextMenu)
。 - 连接
customContextMenuRequested(const QPoint &)
信号到一个槽函数。 - 在槽函数中,创建
QMenu
和QAction
,并使用exec()
显示菜单。
代码示例:
cpp
// 在构造函数中
treeView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(treeView, &QTreeView::customContextMenuRequested,
this, &MainWindow::showContextMenu);
// 槽函数实现
void MainWindow::showContextMenu(const QPoint &pos)
{
// 将视图坐标转换为模型索引
QModelIndex index = treeView->indexAt(pos);
QMenu menu;
QAction *addAction = menu.addAction("添加子项");
QAction *deleteAction = menu.addAction("删除项");
// 如果点击在无效索引上,则禁用某些操作
deleteAction->setEnabled(index.isValid());
QAction *selectedAction = menu.exec(treeView->viewport()->mapToGlobal(pos));
if (selectedAction == addAction) {
// 添加子项的逻辑...
} else if (selectedAction == deleteAction) {
// 删除项的逻辑...
// 注意:删除操作应该通过模型来完成
// model->removeRow(index.row(), index.parent());
}
}
1.6 总结
QTreeView
是一个功能极其强大的控件,其核心在于与 Model 的分离。
- 入门 :使用
QStandardItemModel
可以快速构建树状结构。 - 定制 :通过
set...
系列函数可以轻松改变QTreeView
的外观和交互方式。 - 交互 :利用信号和槽(如
clicked
,customContextMenuRequested
)响应用户操作。 - 进阶 :对于复杂或高性能需求,创建自定义模型继承
QAbstractItemModel
。
二、QTreeWidget
QTreeWidget
是 QTreeView
的一个便捷子类,它将视图(View)和模型(Model)合二为一 ,封装了 QTreeView
和 QStandardItemModel
的组合,使得创建简单的树状结构变得更加容易。
如果你不需要自定义数据结构或复杂的模型逻辑,QTreeWidget
是一个非常好的选择。
2.1 核心概念:QTreeWidget
vs QTreeView
QTreeWidget
: "即插即用" 的树控件。它内部自带一个QStandardItemModel
,你只需要和QTreeWidgetItem
打交道,而不需要关心底层的模型接口。QTreeView
: 高度灵活 的树视图。它必须与一个独立的模型(如QStandardItemModel
或自定义模型)配合使用。这种分离使得它可以处理更复杂的数据和场景。
简单来说,QTreeWidget
是为了方便而设计的,而 QTreeView
是为了灵活而设计的。
2.2 基本用法
使用 QTreeWidget
的核心是 QTreeWidgetItem
,每个 QTreeWidgetItem
代表树中的一个节点(项)。
步骤:
- 创建
QTreeWidget
控件。 - (可选)设置列数和列标题。
- 创建
QTreeWidgetItem
对象作为顶层项(根项)。 - 使用
addTopLevelItem()
将顶层项添加到QTreeWidget
。 - 创建其他
QTreeWidgetItem
对象作为子项。 - 使用
QTreeWidgetItem::addChild()
将子项添加到其父项。
代码示例:
cpp
#include <QApplication>
#include <QMainWindow>
#include <QTreeWidget>
#include <QTreeWidgetItem>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow mainWindow;
mainWindow.setWindowTitle("QTreeWidget 基础示例");
// 1. 创建 QTreeWidget 控件
QTreeWidget *treeWidget = new QTreeWidget(&mainWindow);
// 2. 设置列数和列标题 (如果是多列树)
// 对于单列树,这一步可以省略
QStringList headers;
headers << "项目" << "描述";
treeWidget->setHeaderLabels(headers);
// 3. 创建顶层项 "动物"
QTreeWidgetItem *animalItem = new QTreeWidgetItem(QStringList() << "动物");
// 4. 将顶层项添加到树控件
treeWidget->addTopLevelItem(animalItem);
// 5. 创建子项并添加到 "动物"
QTreeWidgetItem *dogItem = new QTreeWidgetItem(QStringList() << "狗" << "忠诚的伙伴");
QTreeWidgetItem *catItem = new QTreeWidgetItem(QStringList() << "猫" << "高冷的主子");
animalItem->addChild(dogItem);
animalItem->addChild(catItem);
// 6. 创建另一个顶层项 "植物"
QTreeWidgetItem *plantItem = new QTreeWidgetItem(QStringList() << "植物");
treeWidget->addTopLevelItem(plantItem);
// 7. 创建子项并添加到 "植物"
QTreeWidgetItem *flowerItem = new QTreeWidgetItem(QStringList() << "花" << "美丽的植物");
QTreeWidgetItem *treeItem = new QTreeWidgetItem(QStringList() << "树" << "高大的植物");
plantItem->addChild(flowerItem);
plantItem->addChild(treeItem);
// 自动展开所有节点
treeWidget->expandAll();
mainWindow.setCentralWidget(treeWidget);
mainWindow.resize(400, 300);
mainWindow.show();
return a.exec();
}
2.3 常用功能与属性设置
QTreeWidget
的许多方法与 QTreeView
类似,因为它继承自 QTreeView
。
1. 外观定制
setHeaderHidden(bool hidden)
: 隐藏或显示标题栏。setIndentation(int i)
: 设置子项缩进。setRootIsDecorated(bool show)
: 设置是否显示根节点的展开/折叠图标。
2. 交互性设置
setEditTriggers(EditTriggers triggers)
: 设置编辑触发方式。setSelectionMode(SelectionMode mode)
: 设置选择模式。setSelectionBehavior(SelectionBehavior behavior)
: 设置选择行为。
3. 常用操作
-
获取当前选中项 :
cpp// 获取所有选中的项 QList<QTreeWidgetItem*> selectedItems = treeWidget->selectedItems(); if (!selectedItems.isEmpty()) { QTreeWidgetItem *firstSelected = selectedItems.first(); QString text = firstSelected->text(0); // 获取第0列的文本 qDebug() << "当前选中项:" << text; }
-
获取当前项的父/子项 :
cppQTreeWidgetItem *currentItem = treeWidget->currentItem(); if (currentItem) { QTreeWidgetItem *parentItem = currentItem->parent(); int childCount = currentItem->childCount(); // ... }
-
添加/删除项 :
cpp// 添加顶层项 treeWidget->addTopLevelItem(new QTreeWidgetItem(QStringList() << "新顶层项")); // 删除当前选中项 QTreeWidgetItem *currentItem = treeWidget->currentItem(); if (currentItem) { // 如果是顶层项 if (!currentItem->parent()) { int index = treeWidget->indexOfTopLevelItem(currentItem); treeWidget->takeTopLevelItem(index); } else { // 如果是子项 QTreeWidgetItem *parent = currentItem->parent(); int index = parent->indexOfChild(currentItem); parent->takeChild(index); } delete currentItem; // 释放内存 }
-
信号与槽 :
QTreeWidget
同样提供了丰富的信号,如itemClicked
,itemDoubleClicked
,itemPressed
等。cppconnect(treeWidget, &QTreeWidget::itemClicked, [](QTreeWidgetItem *item, int column) { qDebug() << "点击了项:" << item->text(column) << "在列:" << column; });
2.4 右键菜单 (Context Menu)
为 QTreeWidget
添加右键菜单的方法与 QTreeView
类似。
步骤:
- 设置
treeWidget->setContextMenuPolicy(Qt::CustomContextMenu)
。 - 连接
customContextMenuRequested(const QPoint &)
信号。 - 在槽函数中,使用
itemAt(const QPoint &)
获取鼠标位置下的项。
代码示例:
cpp
// 在构造函数中
treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
connect(treeWidget, &QTreeWidget::customContextMenuRequested,
this, &MainWindow::showContextMenu);
// 槽函数实现
void MainWindow::showContextMenu(const QPoint &pos)
{
// 获取鼠标位置下的项
QTreeWidgetItem *item = treeWidget->itemAt(pos);
QMenu menu;
QAction *addAction = menu.addAction("添加子项");
QAction *deleteAction = menu.addAction("删除项");
// 如果没有点击任何项,则禁用操作
addAction->setEnabled(item != nullptr);
deleteAction->setEnabled(item != nullptr);
QAction *selectedAction = menu.exec(treeWidget->viewport()->mapToGlobal(pos));
if (selectedAction == addAction && item) {
item->addChild(new QTreeWidgetItem(QStringList() << "新子项"));
item->setExpanded(true); // 展开父项以显示新子项
} else if (selectedAction == deleteAction && item) {
// 删除项的逻辑...
// ... (同上一节的删除代码)
}
}
2.5 总结:何时使用 QTreeWidget
vs QTreeView
特性 | QTreeWidget |
QTreeView |
---|---|---|
易用性 | 非常高。API 直观,开箱即用。 | 较低。需要理解 Model/View 架构,代码更复杂。 |
灵活性 | 较低。功能被封装,难以深度定制。 | 极高。可以与任何模型(包括自定义模型)配合,实现任何功能。 |
性能 | 对于大数据量可能稍逊。 | 可以通过自定义模型实现懒加载等优化,性能更好。 |
数据来源 | 主要用于内存中的静态或半静态数据。 | 可以连接到数据库、文件系统、网络等任何数据源。 |
推荐场景 | - 简单的配置树 - 文件浏览器的简化版 - 任何不需要复杂数据处理的层级列表 | - 处理海量数据 - 需要自定义数据结构 - 数据来自数据库或其他复杂源 - 需要高度定制的渲染和编辑 |
结论:
- 当你需要快速创建一个简单的、数据量不大的树状列表时,毫不犹豫地选择
QTreeWidget
。 - 当你预见到数据结构会变得复杂,或者性能是一个关键考量时,从一开始就应该使用
QTreeView
和QStandardItemModel
,这样可以避免未来重写大量代码。