一、核心概念与区别
-
Item Views(Model-Based)
- 定义:基于模型-视图架构(Model/View Architecture),通过分离数据存储(Model)与界面展示(View)实现灵活的数据管理。典型控件如
QTreeView、QListView、QTableView - 特点:
- 需手动创建数据模型(如
QStandardItemModel),数据操作通过模型完成 - 支持大规模数据的高效处理(如百万级数据无卡顿)
- 适用于复杂数据逻辑(如动态增删、多视图同步)
- 需手动创建数据模型(如
- 典型控件:
QListView、QTreeView、QTableView。
- 定义:基于模型-视图架构(Model/View Architecture),通过分离数据存储(Model)与界面展示(View)实现灵活的数据管理。典型控件如
-
Item Widgets(Item-Based)
- 定义:基于项的便利类(如
QTreeWidget、QListWidget),内部默认集成数据模型,简化开发流程 - 特点:
- 直接操作项(如
QTreeWidgetItem),无需显式定义模型 - 适合小型数据集(如配置项、静态列表)
- 代码简单但扩展性较差
- 直接操作项(如
- 典型控件:
QListWidget、QTreeWidget、QTableWidget。
- 定义:基于项的便利类(如
二、详细解释:
1. Item Widgets(Item-Based)
第一个控件:QListView
QListView 是 Qt 框架中用于展示列表数据的核心控件,基于模型-视图-委托(Model-View-Delegate)架构,支持灵活的数据管理和交互操作。
QListView常用操作与交互
-
数据操作
- 添加项:通过模型
appendRow()或insertRow()插入数据。 - 删除项:调用模型
removeRow()移除指定行。 - 自定义委托:继承
QStyledItemDelegate实现自定义绘制和交互逻辑。
- 添加项:通过模型
-
信号与事件
- 点击事件:
clicked、doubleClicked等信号传递QModelIndex实现交互响应。 - 右键菜单:通过
setContextMenuPolicy和CustomContextMenu信号实现上下文菜单。
- 点击事件:
-
选择与导航
- 选中项:
setCurrentIndex()设置默认选中行,currentRowChanged信号监听行变化 - 多选模式:通过
setSelectionMode()设置ExtendedSelection支持多选。
- 选中项:
示例项目结构与代码:

widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QListView>
#include <QStringListModel>
#include <QMessageBox>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
QListView* listview1; // 创建QListView对象
private slots:
void SlotClickedFunc(const QModelIndex &index);
};
#endif // WIDGET_H
widget.h
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
resize(450, 250);
listview1 = new QListView(this); // 创建QListView对象
listview1->setGeometry(20, 20, 240, 160); // 设置控件显示位置和控件大小
QStringList qlist;
qlist.append("运动员:篮球、足球");
qlist.append("娱乐类:看电影,写小说、听音乐");
qlist.append("游戏类:五子棋、扑克牌、中国象棋");
qlist.append("旅游类:国内旅游,国外旅游");
// 用数据列表创建数据显示模型进行实现
QStringListModel *listmodel = new QStringListModel(qlist); // 将列表添加进去
listview1->setModel(listmodel);
// 让信号和槽函数进行连接
connect(listview1, SIGNAL(clicked(const QModelIndex)), this, SLOT(SlotClickedFunc(const QModelIndex)));
}
Widget::~Widget()
{
delete ui;
}
void Widget::SlotClickedFunc(const QModelIndex &index){
QMessageBox::information(NULL, "兴趣爱好", "你选择的类型为:\n" + index.data().toString()); // 设置文本
}
实现效果:

第二个控件:QTreeView
一、QTreeView概述
QTreeView 是 Qt 框架中用于展示树形结构数据的核心控件,基于模型-视图架构(Model/View Architecture),通过数据模型(Model)与视图(View)解耦实现灵活的数据管理。
- 适用场景:文件系统目录、组织结构图、多层级配置项等层次化数据展示。
- 核心优势:支持动态数据更新、多视图同步、自定义渲染等复杂操作。
二、常用操作与交互
-
数据操作
- 添加项:通过模型
appendRow()或insertRow()插入数据。 - 删除项:调用模型
removeRow()移除指定行。 - 自定义委托:继承
QStyledItemDelegate实现自定义绘制和交互逻辑。
- 添加项:通过模型
-
信号与事件
- 点击事件:
clicked、doubleClicked等信号传递QModelIndex实现交互响应。 - 右键菜单:通过
setContextMenuPolicy和CustomContextMenu信号实现上下文菜单。
- 点击事件:
-
选择与导航
- 选中项:
setCurrentIndex()设置默认选中行,currentRowChanged信号监听行变化。 - 多选模式:通过
setSelectionMode()设置ExtendedSelection支持多选。
- 选中项:
三、示例代码(首先需要再ui文件中添加一个QTreeView类):

项目目录如下:

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QStringList>
#include <QList>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
public:
void InitTreeViewFunc(); // 初始化树控件视图
QStandardItemModel *sItemModel; // 项目模型变量
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
InitTreeViewFunc(); // 在构造函数调用树视图控件
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::InitTreeViewFunc() // 初始化树视图函数
{
// 1.构造model
sItemModel = new QStandardItemModel(ui->treeView); // 创建树形视图
sItemModel->setHorizontalHeaderLabels(QStringList()<<QStringLiteral("编号")<<QStringLiteral("初中部|高中部"));
// 创建第一个一级节点,将它加入到sItemModel
QList<QStandardItem*> item11; // 数据列表
QStandardItem *item1 = new QStandardItem(QString::number(1));
QStandardItem *item2 = new QStandardItem("初中部");
item11.append(item1);
item11.append(item2);
sItemModel->appendRow(item11); // 添加一级节点
// 二级节点,添加到第一个一级节点
QList<QStandardItem*> item112;
QStandardItem *item1121 = new QStandardItem(QString::number(2));
QStandardItem *item1122 = new QStandardItem("一年级"); // 这个相当于初中部一年级
item112.append(item1121);
item112.append(item1122);
item1->appendRow(item112); // 添加一级节点item1中才有效果
// 三级节点,该三级节点将添加到第一个二级节点
QList<QStandardItem*> item1231;
QStandardItem *item12311 = new QStandardItem(QString::number(3)); // 三级节点的标注
QStandardItem *item12312 = new QStandardItem(QStringLiteral("一班")); // 初中部一年级一班
item1231.append(item12311); // 把这两个加入到三级节点中
item1231.append(item12312);
item1121->appendRow(item1231); // 把三级节点添加到二级节点中的“2”中
// 第二个三级节点
QList<QStandardItem*> item1232;
QStandardItem *item12321 = new QStandardItem(QString::number(3)); // 三级节点的标注
QStandardItem *item12322 = new QStandardItem(QStringLiteral("二班")); // 初中部一年级一班
item1232.append(item12321); // 把这两个加入到三级节点中
item1232.append(item12322);
item1121->appendRow(item1232); // 把三级节点添加到二级节点中的“2”中
// 添加一级节点item12进去,这个是第二个一级节点
QList<QStandardItem*> item12; // 数据列表
QStandardItem *item3 = new QStandardItem(QString::number(2));
QStandardItem *item4 = new QStandardItem("高中部");
item12.append(item3);
item12.append(item4);
sItemModel->appendRow(item12); // 添加一级节点
// 2.给QTreeView应用model
ui->treeView->setModel(sItemModel);
}
实现效果:
2. Item Views(Model-Based)
第一个控件:QListWidget
一、基本概念
- 功能定位:
QListWidget是Qt提供的列表控件,继承自QListView,内置了QStandardItemModel模型,简化了列表项的添加和管理12。 - 核心特性:
- 直接管理
QListWidgetItem对象,每个项可包含文本、图标、复选框等67。 - 支持单/多选、拖放、排序、自定义样式等交互功能37。
- 直接管理
- 特点:通过模型管理数据,视图仅负责展示,支持多视图共享同一模型。
二、核心用法
-
创建与初始化
QListWidget *listWidget = new QListWidget(this); // 创建实例:ml-citation{ref="1,3" data="citationList"} -
添加项
- 基础文本项:
QListWidgetItem *item = new QListWidgetItem("Item 1"); listWidget->addItem(item); // 直接添加:ml-citation{ref="3" data="citationList"} - 带图标的项:
QListWidgetItem *item = new QListWidgetItem(QIcon("icon.png"), "Item 1"); listWidget->addItem(item); // 图标+文本:ml-citation{ref="5" data="citationList"}
- 基础文本项:
-
删除项
- 通过索引删除:
listWidget->takeItem(0); // 移除第1项(返回被移除的项):ml-citation{ref="1,4" data="citationList"} - 清空所有项:
listWidget->clear(); // 清空列表:ml-citation{ref="5" data="citationList"}
- 通过索引删除:
三、交互与事件处理
-
信号与槽
- 点击事件:
connect(listWidget, &QListWidget::itemClicked, [](QListWidgetItem *item) { qDebug() << "选中项:" << item->text(); }); // 单击响应:ml-citation{ref="6,7" data="citationList"} - 选中项变化:
connect(listWidget, &QListWidget::currentItemChanged, [](QListWidgetItem *current, QListWidgetItem *previous) { if (current) qDebug() << "当前项:" << current->text(); }); // 监听选中变化:ml-citation{ref="5,7" data="citationList"}
- 点击事件:
-
右键菜单
listWidget->setContextMenuPolicy(Qt::CustomContextMenu); connect(listWidget, &QListWidget::customContextMenuRequested, [](const QPoint &pos) { QMenu menu; menu.addAction("删除"); menu.exec(QCursor::pos()); // 弹出右键菜单:ml-citation{ref="4,7" data="citationList"} });
QListWidget示例代码:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QListWidgetItem* qitem = new QListWidgetItem("沁园春.雪--作者:毛泽东"); // 给qlistWidget设置一个标题
ui->listWidget->addItem(qitem);
QStringList slist;
qitem->setTextAlignment(Qt::AlignCenter); // 让标题中心对齐
slist << "1.北国风光,千里冰封,万里雪飘。";
slist << "2.望长城内外,惟余莽莽;大河上下,顿时滔滔。";
ui->listWidget->addItems(slist);
}
Widget::~Widget()
{
delete ui;
}
结果:

第二个控件:QTableWidget:
一、基本概念:
QTableWidget 是 Qt 中用于展示和编辑二维表格数据的控件,继承自 QTableView,但内置了默认的数据模型,通过直接操作单元格(QTableWidgetItem)简化开发流程。
- 适用场景:中小规模静态数据(如学生信息表、配置项)或需要快速实现表格功能的场景。
- 核心特点:
- 无需手动创建数据模型,直接通过行、列索引操作单元格。
- 支持单元格内容编辑、样式定制及信号交互
QTableWidget核心方法详解
1. 设置表格行数与列数
- 方法:
setRowCount(int rows)/setColumnCount(int cols) - 功能:
初始化表格的总行数和总列数,用于定义表格的初始结构。 - 示例:
QTableWidget *table = new QTableWidget; table->setRowCount(5); // 初始5行 table->setColumnCount(3); // 初始3列 - 注意事项:
- 若后续动态增删行/列,需调用
insertRow()或removeRow()等接口。 - 设置行数后,未填充数据的行默认显示空白单元格。
- 若后续动态增删行/列,需调用
2. 设置水平表头标签
- 方法:
setHorizontalHeaderLabels(const QStringList &labels) - 功能:
为表格的列设置标题,标题数量需与列数一致。 - 示例:
QStringList headers; headers << "学号" << "姓名" << "成绩"; table->setHorizontalHeaderLabels(headers); // 设置3列标题:ml-citation{ref="1,2" data="citationList"} - 注意事项:
- 若未设置标题,默认显示空表头。
- 支持通过
horizontalHeader()->setStyleSheet()自定义表头样式(如背景色、字体)。
3. 填充单元格数据
- 方法:
setItem(int row, int column, QTableWidgetItem *item) - 功能:
向指定单元格填充数据(文本、图标、复选框等),需创建QTableWidgetItem对象。 - 示例:
// 创建文本项 QTableWidgetItem *idItem = new QTableWidgetItem("2023001"); table->setItem(0, 0, idItem); // 第0行第0列填充数据:ml-citation{ref="1,6" data="citationList"} // 创建带复选框的项 QTableWidgetItem *checkItem = new QTableWidgetItem("未完成"); checkItem->setCheckState(Qt::Unchecked); // 设置复选框状态:ml-citation{ref="1,5" data="citationList"} table->setItem(0, 1, checkItem); - 注意事项:
QTableWidgetItem需手动管理内存(建议通过new创建并设置父对象)。- 若单元格未初始化(未调用
setItem()),直接访问可能导致程序崩溃。
4. 动态增删行
- 方法:
insertRow(int row)/removeRow(int row) - 功能:
在指定位置插入新行或删除已有行,支持动态调整表格结构。 - 示例:
// 在第2行插入新行(原第2行及后续行下移) table->insertRow(1); table->setItem(1, 0, new QTableWidgetItem("2023002")); // 删除第0行(后续行上移) table->removeRow(0); - 注意事项:
- 插入行时需确保新行索引不超过当前行数范围(否则无效)。
- 删除行后,原行索引后续的行会自动前移。
5. 综合应用示例
// 创建表格并初始化
QTableWidget table;
table.setRowCount(3);
table.setColumnCount(2);
table.setHorizontalHeaderLabels({"姓名", "年龄"});
// 填充数据
table.setItem(0, 0, new QTableWidgetItem("张三"));
table.setItem(0, 1, new QTableWidgetItem("25"));
table.setItem(1, 0, new QTableWidgetItem("李四"));
table.setItem(1, 1, new QTableWidgetItem("30"));
// 动态插入行
table.insertRow(2);
table.setItem(2, 0, new QTableWidgetItem("王五"));
table.setItem(2, 1, new QTableWidgetItem("28"));
QTableWidget 总结
QTableWidget 的 setRowCount()、setColumnCount() 等方法用于定义表格基础结构,setItem() 和动态增删接口实现数据填充与管理。通过合理调用这些方法,可快速构建功能完整的表格界面。
第三个控件:QTreeWidget
一、基本概念:
QTreeWidget 是 Qt 中基于项的树形控件,继承自 QTreeView,但内置默认数据模型,通过直接操作节点(QTreeWidgetItem)实现树形结构的快速构建。
- 适用场景:静态层级数据展示(如文件目录、组织架构、配置树等)。
- 核心特点:
- 无需手动创建数据模型,直接通过节点对象管理层级关系。
- 支持多列显示、节点展开/折叠、复选框交互及自定义样式。
二、核心方法与操作
1. 控件初始化
| 方法 | 功能说明 | 示例 |
|---|---|---|
setColumnCount(int) | 设置控件显示的列数(默认1列) | tree->setColumnCount(2); |
setHeaderLabels(QStringList) | 设置表头标题(需与列数一致) | tree->setHeaderLabels({"名称", "ID"}); |
2. 节点管理
- 添加节点:
// 添加根节点
QTreeWidgetItem *root = new QTreeWidgetItem(tree);
root->setText(0, "总部");
tree->addTopLevelItem(root); // 必须调用此方法显示根节点:ml-citation{ref="5,6" data="citationList"}
// 添加子节点
QTreeWidgetItem *child = new QTreeWidgetItem(root);
child->setText(0, "技术部");
- 删除节点:
delete child; // 直接释放对象(需确保无其他引用):ml-citation{ref="4" data="citationList"}
或
root->removeChild(child); // 从父节点移除子节点:ml-citation{ref="4" data="citationList"}
3. 数据与属性设置
- 节点数据存储:
child->setData(0, Qt::UserRole, 100); // 存储自定义数据(如ID):ml-citation{ref="5,6" data="citationList"}
int id = child->data(0, Qt::UserRole).toInt(); // 读取数据:ml-citation{ref="5,6" data="citationList"}
- 设置图标与样式:
child->setIcon(0, QIcon(":/icon.png")); // 设置节点图标:ml-citation{ref="3,6" data="citationList"}
child->setBackground(0, QBrush(Qt::yellow)); // 设置背景色:ml-citation{ref="6,7" data="citationList"}
三、高级功能
1. 复选框功能
// 启用复选框
child->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
child->setCheckState(0, Qt::Unchecked); // 初始状态:ml-citation{ref="3,4" data="citationList"}
// 信号处理勾选事件
connect(tree, &QTreeWidget::itemChanged, [](QTreeWidgetItem *item, int col) {
if (item->checkState(col) == Qt::Checked) {
qDebug() << "选中节点:" << item->text(0);
}
});
2. 动态交互与优化
- 展开/折叠控制:
tree->expandItem(root); // 展开节点:ml-citation{ref="1,3" data="citationList"}
tree->collapseItem(child); // 折叠节点:ml-citation{ref="1,3" data="citationList"}
- 排序功能:
tree->setSortingEnabled(true); // 启用排序:ml-citation{ref="8" data="citationList"}
tree->sortByColumn(0, Qt::AscendingOrder); // 按首列升序排列:ml-citation{ref="8" data="citationList"}
四、与QTreeView的对比
| 特性 | QTreeWidget | QTreeView |
|---|---|---|
| 开发效率 | 高(直接操作节点,无需模型) | 低(需自定义模型,如 QStandardItemModel) |
| 适用场景 | 静态数据(如配置树、小型目录) | 动态数据(如数据库查询结果、大规模文件系统) |
五、注意事项
- 性能问题:
- 数据量超过 1000 节点 时,建议改用
QTreeView+ 自定义模型。
- 数据量超过 1000 节点 时,建议改用
- 内存管理:
- 手动删除节点时需确保无父节点引用,否则可能引发内存泄漏。
- 交互设计:
- 避免同时启用多选模式和复选框,防止用户操作冲突。
三、适用场景对比
| 场景 | Item Widgets | Item Views |
|---|---|---|
| 数据规模 | 小型数据(<1000项) | 大规模数据(>10000项) |
| 开发复杂度 | 快速实现,代码简单 | 需额外模型定义,较复杂 |
| 扩展性 | 低(数据与界面耦合) | 高(数据与界面分离) |
四、设计思想与性能分析
-
继承关系
Item Widgets(如QTreeWidget)继承自Item Views(如QTreeView),属于其便利子类。- 例如:
QTreeWidget继承QTreeView,并内置默认模型。
-
性能差异
Item Views通过模型代理机制优化渲染,减少内存占用;Item Widgets直接操作项,数据量大时易卡顿。
五、最佳实践建议
-
选择依据
- 优先使用
Item Views处理动态或复杂数据。 - 快速原型开发可选用
Item Widgets。
- 优先使用
总结
Item Views 与 Item Widgets 是 Qt 中数据展示的两种核心方案。前者以模型驱动为核心,适合高性能场景;后者以项操作为核心,简化开发流程。理解其差异与适用场景,可显著提升 Qt 应用的开发效率与性能表现。个人感觉这两个是差不多的。
写在最后:
我们可以在这里学习C++知识:


392

被折叠的 条评论
为什么被折叠?



