开篇介绍:
hello 大家,本篇博客我们来学习QTableWidget常见属性以及QTableWidgetItem类。
在 Qt 桌面应用开发中,当我们需要展示和管理 "一维列表"(比如联系人列表、播放列表)时,QListWidget 是我们的首选;但当我们需要展示和管理更复杂的 "二维表格数据"(比如学生信息表、商品库存表、财务报表)时 ------ 也就是数据既有 "行" 又有 "列",每个数据都有明确的 "行号 + 列号" 定位时,我们就需要一个更强大的控件:QTableWidget(表格控件)。
QTableWidget 就像 "我们平时用的 Excel 表格"------ 它由若干行和若干列组成,行和列的交叉点就是一个 "单元格";你可以设置表格有多少行、多少列,可以给每一列起个名字(列标题),给每一行起个名字(行标题);你可以在任意单元格里填写文字、贴图标、改字体、设置对齐方式;你可以点击单元格、双击单元格、鼠标悬浮在单元格上;你可以动态插入新的一行、新的一列,也可以删除某一行、某一列。
而 QTableWidget 中的每一个 "单元格",都是由 QTableWidgetItem(表格项类) 来表示的 ------QTableWidgetItem 是 QTableWidget 的最小组成单元,对应表格中 "行 + 列" 定位的单个单元格;它的属性和 QListWidgetItem 几乎一模一样,只不过多了 "列号" 的概念。
很多新手刚接触 QTableWidget 和 QTableWidgetItem 时,会觉得它们比 QListWidget 复杂 ------ 毕竟多了一维,要同时考虑行和列。但别担心!只要你掌握了 QListWidget,学习 QTableWidget 就会非常轻松,因为它们的核心逻辑是相通的:QListWidget 是 "一维数组",QTableWidget 是 "二维数组";QListWidgetItem 是 "一维数组的元素",QTableWidgetItem 是 "二维数组的元素"。
这篇文章我会先讲 QTableWidgetItem 类的核心方法 (row、column、setText、setTextAlignment、setIcon、setSelected、setSizeHint、setFont),再讲 QTableWidget 的核心方法 (item、setItem、currentItem、currentRow、currentColumn、row、column、rowCount、columnCount、insertRow、insertColumn、removeRow、removeColumn、setHorizontalHeaderItem、setVerticalHeaderItem),接着讲 QTableWidget 的核心交互信号 (cellClicked、cellDoubleClicked、cellEntered、currentCellChanged),最后是综合示例。
话不多说,我们正式开始!
第一章 先搞懂基础:QTableWidget 和 QTableWidgetItem 是什么?
在讲具体内容之前,我们必须先搞懂两个最基础、最重要的问题:QTableWidget 是用来做什么的?QTableWidgetItem 是用来做什么的?以及,它们和 QTableView 的关系是什么?
1.1 QTableWidget 的核心定位
QTableWidget 是 Qt Widgets 模块中用于展示和管理二维表格数据的核心通用控件 ------ 它继承自 QTableView(表格视图),但比 QTableView 更简单、更易用,因为它内置了 "单元格管理" 的功能,不需要你手动实现数据模型(Model)和视图(View)的分离。
通俗理解:QTableWidget 就像 "一个简化版的 Excel 表格"------ 它是一个二维的网格,由 "行" 和 "列" 组成;行是纵向的,列是横向的;行和列的交叉点就是一个 "单元格";你可以在单元格里填数据、改样式;你可以增加行、增加列、删除行、删除列;你可以给列起标题(比如 "姓名""年龄""学号"),给行起标题(比如 "第一行""第二行")。

QTableWidget 内置了非常多的功能,不需要你手动实现:
- 它支持按 "行号 + 列号" 精准定位和操作单元格;
- 它支持获取当前选中的单元格、选中的行号、选中的列号;
- 它支持统计表格的总行数、总列数;
- 它支持在指定位置插入新行、新列,删除指定行、指定列;
- 它支持自定义水平表头(列标题)和垂直表头(行标题);
- 它支持丰富的交互信号:单元格点击、双击、鼠标悬浮、选中变更等;
- 它的样式可以通过 QSS(Qt 样式表)完全自定义。
总之,QTableWidget 是桌面端 "展示和管理二维表格数据" 场景的通用首选组件------ 只要是想展示一个表格,用 QTableWidget 就对了。
1.2 QTableWidgetItem 的核心定位
QTableWidgetItem 是 Qt 中表示 QTableWidget 中单个单元格的核心类------ 它是 QTableWidget 的最小组成单元,每个 QTableWidgetItem 对应表格中 "行 + 列" 定位的单个单元格。
通俗理解:QTableWidgetItem 就像 "Excel 表格里的每一个小格子"------ 这个小格子里可以写文字(setText),可以贴图标(setIcon),可以设置字体(setFont),可以设置文字对齐方式(setTextAlignment);你可以把这个格子标记为 "已选中"(setSelected),可以设置这个格子的大小(setSizeHint);你还可以查询这个格子在第几行(row)、第几列(column)。
QTableWidgetItem 的核心特征和 QListWidgetItem 几乎一模一样,只是多了 "列号" 的概念:
- 它本质上是一个 "文本 + 图标" 的组合体 ------ 这是它最核心的视觉内容;
- 每个单元格可以独立设置样式和状态------ 你可以让第一个单元格是红色字体,第二个单元格是蓝色字体,第三个单元格带图标;
- 它支持查询自身的行号和列号 ------ 未加入表格时返回 -1;
- 它的内存由 QTableWidget 管理(通过
setItem添加后)------ 通过removeRow/removeColumn移除时会自动释放。
1.3 QTableWidget 和 QTableView 的关系(必知!)
和 QListWidget 与 QListView 的关系一样:
- QTableWidget 是 QTableView 的子类 ------ 它在 QTableView 的基础上,内置了一个简单的数据模型(
QStandardItemModel),让你可以直接操作单元格,而不需要手动实现 Model/View 架构; - QTableWidget 比 QTableView 更简单、更易用------ 如果你只是想展示一个简单的表格,不需要复杂的数据模型,用 QTableWidget 就够了;如果你需要展示大量数据(比如成千上万条),或者需要自定义数据模型,再考虑用 QTableView + 自定义 Model。
1.4 一个超级重要的注意事项(开篇就讲,刻在脑子里!)
在正式开始之前,有一个超级重要、新手最容易踩坑、一踩就无效的注意事项,必须开篇就讲,刻在脑子里:
严格注意!在插入条目(setItem)之前,必须先指明表格的行列数量才行哦!
你可以用
setRowCount()设置行数,用setColumnCount()设置列数;或者用
insertRow()和insertColumn()先插入行列;否则,你设置的单元格可能无效,界面上看不到内容!
通俗理解:你要先把 "表格的格子画好"(设置行列数),才能往 "格子里填东西"(设置单元格);如果格子都没画好,你填的东西就没地方放,界面上自然看不到。
这个注意事项超级重要,后面讲 setItem 时我还会再强调,但现在必须先记住!
第二章 QTableWidgetItem 类核心方法详解
好,我们正式开始!按照你提供的顺序,我们首先讲 QTableWidgetItem 类的核心方法 ------ 因为要往 QTableWidget 里填单元格,首先得搞懂单元格本身怎么设置。QTableWidgetItem 的方法和 QListWidgetItem 几乎一模一样,只是多了 row() 和 column() 两个方法,用来查询单元格的位置。
2.1 方法一:row ()------ 获取当前单元格所属的行号
2.1.1 方法的核心定义
row() 是 QTableWidgetItem 用于获取当前单元格所属行号的核心位置查询方法 ------ 行号从 0 开始计数(第一行是 0,第二行是 1,以此类推);若条目未添加到表格中,返回值为 -1。
通俗理解:row() 就像 "问这个小格子:'你在表格的第几行呀?'"------ 它会告诉你一个数字,从 0 开始;如果这个小格子还没放到表格里,它就说 "我不知道"(返回 -1)。
这里有几个超级重要的规则,必须牢记:
- 行号从 0 开始计数!(超级重要!说三遍!) :
- 第一行的行号是 0,第二行是 1,第三行是 2,...,第 N 行是 N-1;
- 用户视角的 "第 1 行" 对应代码里的
row=0,这点新手非常容易搞错!
- 未加入表格返回 -1 :条目创建后,未通过
setItem()添加到表格时,返回 -1; - 位置联动(超级重要!) :
- 条目添加到表格后,行号随表格行增删自动更新;
- 比如删除了上方的行,这个条目的行号会自动 -1;
- 比如在上方插入了新行,这个条目的行号会自动 +1;
- 等价方法 :
table->row(item)和item->row()是等价的,结果完全一致。
2.1.2 关联 API 详解(逐词逐句,零模糊)
1. 获取当前单元格所属行号:int row () const
函数原型:
int QTableWidgetItem::row() const;
逐词逐句底层解析:
int:返回值类型,返回行号;QTableWidgetItem:::说明这个函数是QTableWidgetItem类的成员函数,只能用 QTableWidgetItem 对象调用;row():函数名,很直观,就是 "获取行号" 的意思;const:常成员函数,不会修改条目状态。
返回值说明:
- 返回
int类型的整数; - 有效范围:
0 ≤ row < rowCount()(已加入表格时); - 未加入表格时返回
-1。
2.1.3 使用示例
#include <QTableWidgetItem>
#include <QDebug>
// 假设表格已经设置了 3 行 3 列
// 获取第 2 行(索引 1)、第 3 列(索引 2)的单元格
QTableWidgetItem* item = ui->tableWidget->item(1, 2);
if (item != nullptr) { // 判空
int rowNum = item->row();
qDebug() << "单元格行号(代码):" << rowNum; // 输出:1
qDebug() << "单元格行号(用户):" << rowNum + 1; // 行号+1 适配用户习惯,输出:2
}
2.1.4 关键注意事项(必知!)
- 行号从 0 开始!(超级重要!说三遍!):用户视角的第 1 行对应代码的 0;
- 未加入表格返回 -1;
- 位置联动(超级重要!):行号随表格行增删自动更新;
- 等价于 table->row (item)。
2.2 方法二:column ()------ 获取当前单元格所属的列号
2.2.1 方法的核心定义
column() 是 QTableWidgetItem 用于获取当前单元格所属列号的核心位置查询方法 ------ 列号从 0 开始计数(第一列是 0,第二列是 1,以此类推);若条目未添加到表格中,返回值为 -1。
通俗理解:column() 就像 "问这个小格子:'你在表格的第几列呀?'"------ 它会告诉你一个数字,从 0 开始;如果这个小格子还没放到表格里,它就说 "我不知道"(返回 -1)。
这里有几个超级重要的规则,必须牢记:
- 列号从 0 开始计数!(超级重要!说三遍!) :
- 第一列的列号是 0,第二列是 1,第三列是 2,...,第 N 列是 N-1;
- 用户视角的 "第 1 列" 对应代码里的
column=0;
- 未加入表格返回 -1 :条目创建后,未通过
setItem()添加到表格时,返回 -1; - 位置联动(超级重要!) :
- 条目添加到表格后,列号随表格列增删自动更新;
- 比如删除了左侧的列,这个条目的列号会自动 -1;
- 比如在左侧插入了新列,这个条目的列号会自动 +1;
- 等价方法 :
table->column(item)和item->column()是等价的,结果完全一致。
2.2.2 关联 API 详解(逐词逐句,零模糊)
1. 获取当前单元格所属列号:int column () const
函数原型:
int QTableWidgetItem::column() const;
逐词逐句底层解析:
int:返回值类型,返回列号;QTableWidgetItem:::成员函数;column():函数名,"获取列号" 的意思;const:常成员函数。
返回值说明:
- 返回
int类型的整数; - 有效范围:
0 ≤ column < columnCount()(已加入表格时); - 未加入表格时返回
-1。
2.2.3 使用示例
#include <QTableWidgetItem>
#include <QDebug>
// 假设表格已经设置了 3 行 3 列
// 遍历表格第一行(索引 0),打印每个单元格的列号和文本
for (int col = 0; col < ui->tableWidget->columnCount(); ++col) {
QTableWidgetItem* item = ui->tableWidget->item(0, col);
if (item != nullptr) { // 判空
qDebug() << "列号(代码):" << item->column()
<< ",列号(用户):" << item->column() + 1
<< ",文本:" << item->text();
}
}
2.2.4 关键注意事项(必知!)
- 列号从 0 开始!(超级重要!说三遍!):用户视角的第 1 列对应代码的 0;
- 未加入表格返回 -1;
- 位置联动(超级重要!):列号随表格列增删自动更新;
- 等价于 table->column (item)。
2.3 方法三:setText () & text ()------ 设置 / 获取单元格文本
这两个方法和 QListWidgetItem 的 setText()/text() 几乎一模一样,我们简单回顾一下,重点讲和表格相关的注意事项。
2.3.1 方法的核心定义
setText() 用于设置单元格的显示文本,支持普通字符串、HTML 富文本格式;text() 用于获取当前单元格显示的文本。
通俗理解:setText() 就像 "在这个小格子里写字";text() 就像 "读这个小格子里写的是什么字"。
表格相关的关键注意事项:
- 文本过长时自动截断 :文本过长时,表格会自动截断并显示省略号,可通过
setSizeHint()扩大单元格尺寸,或通过resizeColumnsToContents()自动调整列宽来避免; - 富文本支持 :仅支持基础 HTML 标签(
<b>/<i>/<font>/<br>等),复杂标签可能无法正常渲染; - 编码适配:确保文本为 UTF-8 编码,避免中文乱码。
2.3.2 使用示例
#include <QTableWidgetItem>
// 假设表格已经设置了行列数
// 示例1:设置普通文本
QTableWidgetItem* item1 = new QTableWidgetItem();
item1->setText("普通文本单元格");
ui->tableWidget->setItem(0, 0, item1);
// 示例2:设置富文本(红色加粗)
QTableWidgetItem* item2 = new QTableWidgetItem();
item2->setText("<font color='red'><b>富文本单元格(红色加粗)</b></font>");
ui->tableWidget->setItem(0, 1, item2);
// 示例3:获取单元格文本
QString text = item1->text();
qDebug() << "单元格文本:" << text;
2.4 方法四:setTextAlignment ()------ 设置单元格文本对齐方式
这个方法和 QListWidgetItem 的 setTextAlignment() 几乎一模一样,我们简单回顾一下。
2.4.1 方法的核心定义
setTextAlignment() 用于控制文本在单元格内部的水平 + 垂直对齐位置,默认对齐方式为 Qt::AlignLeft | Qt::AlignVCenter(左对齐 + 垂直居中);对齐效果需结合单元格尺寸(setSizeHint)或列宽 / 行高调整才能明显体现。
核心对齐枚举值(Qt::Alignment)(和之前完全一样):
| 枚举值 | 功能说明 | |
|---|---|---|
Qt::AlignLeft |
水平左对齐(默认); | |
Qt::AlignRight |
水平右对齐; | |
Qt::AlignHCenter |
水平居中; | |
Qt::AlignCenter |
水平 + 垂直居中(等价于 `AlignHCenter | AlignVCenter`); |
Qt::AlignTop |
垂直顶部对齐; | |
Qt::AlignBottom |
垂直底部对齐; | |
Qt::AlignVCenter |
垂直居中(默认); |
2.4.2 使用示例
#include <QTableWidgetItem>
#include <QSize>
#include <Qt>
// 假设表格已经设置了行列数
// 示例1:设置单元格文本水平+垂直居中
QTableWidgetItem* item1 = new QTableWidgetItem("居中对齐");
item1->setTextAlignment(Qt::AlignCenter);
item1->setSizeHint(QSize(100, 50)); // 扩大单元格尺寸,对齐效果更明显
ui->tableWidget->setItem(1, 0, item1);
// 示例2:设置文本右对齐+垂直底部对齐
QTableWidgetItem* item2 = new QTableWidgetItem("右底对齐");
item2->setTextAlignment(Qt::AlignRight | Qt::AlignBottom);
ui->tableWidget->setItem(1, 1, item2);
2.5 方法五:setIcon () & icon ()------ 设置 / 获取单元格图标
这个方法和 QListWidgetItem 的 setIcon()/icon() 几乎一模一样,我们简单回顾一下,重点讲和表格相关的注意事项。
2.5.1 方法的核心定义
setIcon() 用于为单元格添加 / 修改图标,图标默认显示在文本左侧;icon() 用于获取当前单元格的图标。
表格相关的关键注意事项:
- 图标显示尺寸由 QTableWidget 全局控制!(超级重要!) :
- 单个单元格无法单独设置图标的显示尺寸;
- 所有单元格的图标显示尺寸由 QTableWidget 的
setIconSize()方法全局统一控制;
- 支持多种图标来源:资源文件、本地图片、系统图标等;
- QIcon 自动适配状态:自动适配单元格选中 / 未选中状态。
2.5.2 使用示例
#include <QTableWidgetItem>
#include <QIcon>
#include <QApplication>
#include <QStyle>
// 先设置 QTableWidget 的全局图标尺寸(超级重要!所有单元格共用!)
ui->tableWidget->setIconSize(QSize(24, 24)); // 图标显示为 24x24 像素
// 假设表格已经设置了行列数
// 示例1:使用资源文件图标
QTableWidgetItem* item1 = new QTableWidgetItem("资源图标");
item1->setIcon(QIcon(":/images/icon.png"));
ui->tableWidget->setItem(2, 0, item1);
// 示例2:使用系统图标
QTableWidgetItem* item2 = new QTableWidgetItem("系统图标");
QIcon systemIcon = QApplication::style()->standardIcon(QStyle::SP_FileIcon);
item2->setIcon(systemIcon);
ui->tableWidget->setItem(2, 1, item2);
2.6 方法六:setSelected () & isSelected ()------ 设置 / 获取单元格是否选中
这个方法和 QListWidgetItem 的 setSelected()/isSelected() 几乎一模一样,我们简单回顾一下,重点讲和表格相关的注意事项。
2.6.1 方法的核心定义
setSelected() 用于控制单元格的选中状态,选中的单元格会按照系统 / 自定义样式高亮显示;isSelected() 用于判断单元格是否被选中。
表格相关的关键注意事项:
- 受表格选择模式控制 :仅在非
NoSelection模式下,选中状态才会生效; - 受表格选择行为控制 :
- 若表格开启
setSelectionBehavior(QAbstractItemView::SelectRows),选中单元格会同步选中整行; - 若开启
SelectColumns,选中单元格会同步选中整列;
- 若表格开启
- 信号触发 :调用
setSelected()会触发QTableWidget::itemSelectionChanged()信号。
2.6.2 使用示例
#include <QTableWidgetItem>
#include <QAbstractItemView>
// 假设表格已经设置了行列数
// 示例1:设置表格为单选模式,选中指定单元格
ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
QTableWidgetItem* item1 = new QTableWidgetItem("选中单元格");
item1->setSelected(true);
ui->tableWidget->setItem(3, 0, item1);
// 示例2:判断单元格是否选中
if (item1->isSelected()) {
qDebug() << "单元格被选中了";
}
2.7 方法七:setSizeHint () & sizeHint ()------ 设置 / 获取单元格尺寸提示
这个方法和 QListWidgetItem 的 setSizeHint()/sizeHint() 几乎一模一样,我们简单回顾一下,重点讲和表格相关的注意事项。
注意! 你提供的资料里写的是 setSizeHints,这是一个笔误!Qt 官方的正确方法名是 setSizeHint(单数),没有 setSizeHints(复数)这个方法,这里我们修正过来。
2.7.1 方法的核心定义
setSizeHint() 用于为单个单元格设置固定尺寸提示,优先级高于 QTableWidget 的默认单元格尺寸;未设置时,单元格尺寸由内容(文本 + 图标)和表格列宽 / 行高自动计算。
表格相关的关键注意事项:
- 行列适配(超级重要!) :
- 单元格宽度受表格列宽限制 ------ 若列宽 <
size.width(),则按列宽显示; - 单元格高度受表格行高限制 ------ 若表格设置
setUniformRowHeights(true)(统一行高),单元格高度设置失效;
- 单元格宽度受表格列宽限制 ------ 若列宽 <
- 最小尺寸限制:设置的尺寸小于内容最小显示尺寸时,自动适配为内容最小尺寸。
2.7.2 使用示例
#include <QTableWidgetItem>
#include <QSize>
// 假设表格已经设置了行列数
// 设置单元格固定尺寸(宽 150px,高 40px)
QTableWidgetItem* item = new QTableWidgetItem("自定义尺寸");
item->setSizeHint(QSize(150, 40));
ui->tableWidget->setItem(4, 0, item);
2.8 方法八:setFont () & font ()------ 设置 / 获取单元格字体样式
这个方法和 QListWidgetItem 的 setFont()/font() 几乎一模一样,我们简单回顾一下。
2.8.1 方法的核心定义
setFont() 用于自定义单个单元格的字体(大小、粗细、字体家族等),优先级高于 QTableWidget 的全局字体设置;未单独设置时,继承表格的全局字体样式。
关键注意事项:
- 颜色独立(超级重要!) :QFont 仅控制字体样式(大小 / 粗细 / 家族),文本颜色需通过
setForeground()设置,不是setFont()! - 优先级:单个单元格字体 > 表格全局字体 > 应用程序默认字体;
- 动态生效:设置后立即刷新单元格视觉效果。
2.8.2 使用示例
#include <QTableWidgetItem>
#include <QFont>
#include <QGuiApplication> // Qt::red 等颜色定义
// 假设表格已经设置了行列数
// 设置单元格字体(微软雅黑、14号、粗体)
QTableWidgetItem* item = new QTableWidgetItem("自定义字体");
QFont font("Microsoft YaHei", 14, QFont::Bold);
item->setFont(font);
// 额外设置文本颜色(QFont 不包含颜色,需通过 setForeground)
item->setForeground(Qt::blue);
ui->tableWidget->setItem(4, 1, item);
示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//OK大家,在我们前面学习完了QListWidget控件之后,我们知道,它的本质就是一个一维数组
//一个简单的列表,每一个条目都要占一行,那么有一维数组,自然就有二维数组
//所以接下来,我们要学习QTableWidget控件
//这个控件其实是和QListWidget控件差不多的,只不过它能支持我们设置条目在某行某列
//说白了其实也就是一个二维数组罢了~~~~~
//那么一样的,QTableWidget也有自己的条目类,那就是QTableWidgetItem类
//其实它的属性和QListWidgetItem类可以说是一模一样的,所以呢,我们就能轻而易举的学习
//相比而言,就多了一个column罢了,用它获取所在列数
/**
* @class QTableWidgetItem
* @brief Qt中QTableWidget表格控件的单元格条目类,表征表格中的单个单元格
* @details QTableWidgetItem是QTableWidget的最小组成单元,对应表格中"行+列"定位的单个单元格;
* 核心支持行/列位置查询、文本/图标/字体/对齐方式/尺寸/选中状态的自定义配置,是表格单元格视觉与状态定制的核心类。
*
* 【核心特征】
* 1. 位置定位:可查询单元格所属的行/列号(未加入表格时返回-1);
* 2. 视觉定制:支持文本、图标、字体、对齐方式、尺寸的个性化设置;
* 3. 状态控制:支持选中状态的手动设置,适配表格的单选/多选交互场景。
*/
// ============================== 核心方法详解 ==============================
/**
* @fn int QTableWidgetItem::row() const
* @brief 获取当前单元格条目所属的**行号**
* @details 核心位置查询方法,返回该条目在QTableWidget中的行索引,行号从0开始计数;
* 若条目未添加到表格中,返回值为-1。
*
* @返回值说明:
* @return int - 单元格行号(0开始,未加入表格返回-1)。
*
* @使用示例:
* // 获取指定单元格的行号
* QTableWidgetItem* item = ui->tableWidget->item(1, 2); // 获取第2行第3列单元格
* if (item) {
* int rowNum = item->row();
* qDebug() << "单元格行号:" << rowNum; // 输出:1
* }
*
* 【关键注意事项】
* 1. 行号规则:行号从0开始,第一行=0、第二行=1,以此类推;
* 2. 未加入表格:条目创建后未通过setItem()添加到表格时,返回-1;
* 3. 位置联动:条目添加到表格后,行号随表格行增删(如删除上方行)自动更新。
*/
/**
* @fn int QTableWidgetItem::column() const
* @brief 获取当前单元格条目所属的**列号**
* @details 核心位置查询方法,返回该条目在QTableWidget中的列索引,列号从0开始计数;
* 若条目未添加到表格中,返回值为-1。
*
* @返回值说明:
* @return int - 单元格列号(0开始,未加入表格返回-1)。
*
* @使用示例:
* // 遍历表格第一行,打印每个单元格的列号
* for (int col = 0; col < ui->tableWidget->columnCount(); ++col) {
* QTableWidgetItem* item = ui->tableWidget->item(0, col);
* if (item) {
* qDebug() << "列号:" << item->column() << ",文本:" << item->text();
* }
* }
*
* 【关键注意事项】
* 1. 列号规则:列号从0开始,第一列=0、第二列=1,以此类推;
* 2. 未加入表格:条目未添加到表格时返回-1,与row()规则一致;
* 3. 位置联动:列号随表格列增删(如删除左侧列)自动更新。
*/
/**
* @fn void QTableWidgetItem::setText(const QString& text)
* @brief 设置单元格的显示文本
* @details 单元格核心内容配置方法,支持普通字符串、HTML富文本格式;
* 文本是单元格的核心展示内容,未设置时单元格显示为空。
*
* @参数说明:
* @param text - QString类型,单元格要显示的文本内容(支持UTF-8编码,可包含中文、特殊字符)。
*
* @使用示例:
* // 1. 设置普通文本
* QTableWidgetItem* item1 = new QTableWidgetItem();
* item1->setText("普通文本单元格");
* ui->tableWidget->setItem(0, 0, item1);
*
* // 2. 设置富文本(红色加粗)
* QTableWidgetItem* item2 = new QTableWidgetItem();
* item2->setText("<font color='red'><b>富文本单元格</b></font>");
* ui->tableWidget->setItem(0, 1, item2);
*
* 【关键注意事项】
* 1. 富文本支持:仅基础HTML标签(<b>/<i>/<font>/<br>等),复杂标签可能无法正常渲染;
* 2. 文本截断:文本过长时,表格会自动截断并显示省略号,可通过setSizeHint扩大单元格尺寸避免;
* 3. 编码适配:确保文本为UTF-8编码,避免中文乱码(Qt默认支持,需注意文件编码格式)。
*/
/**
* @fn void QTableWidgetItem::setTextAlignment(int alignment)
* @brief 设置单元格文本的对齐方式
* @details 控制文本在单元格内部的水平+垂直对齐位置,默认对齐方式为Qt::AlignLeft | Qt::AlignVCenter;
* 对齐效果需结合单元格尺寸(setSizeHint)才能明显体现。
*
* 【核心对齐枚举值(Qt::Alignment)】
* | 枚举值 | 功能说明 |
* |-----------------------|--------------------------------------------------------------------------|
* | Qt::AlignLeft | 水平左对齐(默认); |
* | Qt::AlignRight | 水平右对齐; |
* | Qt::AlignHCenter | 水平居中; |
* | Qt::AlignCenter | 水平+垂直居中(等价于AlignHCenter | AlignVCenter); |
* | Qt::AlignTop | 垂直顶部对齐; |
* | Qt::AlignBottom | 垂直底部对齐; |
* | Qt::AlignVCenter | 垂直居中(默认); |
*
* @参数说明:
* @param alignment - int类型,可组合多个Qt::Alignment枚举值(用|连接)。
*
* @使用示例:
* // 设置单元格文本水平+垂直居中
* QTableWidgetItem* item = new QTableWidgetItem("居中对齐");
* item->setTextAlignment(Qt::AlignCenter);
* item->setSizeHint(QSize(100, 50)); // 扩大单元格尺寸,对齐效果更明显
* ui->tableWidget->setItem(1, 0, item);
*
* // 设置文本右对齐+垂直底部对齐
* QTableWidgetItem* item2 = new QTableWidgetItem("右底对齐");
* item2->setTextAlignment(Qt::AlignRight | Qt::AlignBottom);
* ui->tableWidget->setItem(1, 1, item2);
*
* 【关键注意事项】
* 1. 组合使用:对齐方式可通过|组合(如Qt::AlignHCenter | Qt::AlignTop);
* 2. 尺寸影响:单元格尺寸过小时,对齐效果不明显,需配合setSizeHint调整;
* 3. 图标兼容:图标始终显示在文本左侧,不受文本对齐方式影响。
*/
/**
* @fn void QTableWidgetItem::setIcon(const QIcon& icon)
* @brief 设置单元格的显示图标
* @details 为单元格添加/修改图标,图标默认显示在文本左侧,是实现"图标+文本"单元格的核心方法;
* 未设置时单元格仅显示文本,无图标。
*
* @参数说明:
* @param icon - QIcon类型,支持本地图片、资源文件、系统图标等多种图标来源。
*
* @使用示例:
* // 1. 使用资源文件图标
* QTableWidgetItem* item1 = new QTableWidgetItem("资源图标");
* item1->setIcon(QIcon(":/images/icon.png"));
* ui->tableWidget->setItem(2, 0, item1);
*
* // 2. 使用系统图标
* QTableWidgetItem* item2 = new QTableWidgetItem("系统图标");
* item2->setIcon(QApplication::style()->standardIcon(QStyle::SP_FileIcon));
* ui->tableWidget->setItem(2, 1, item2);
*
* // 设置表格内所有图标的统一显示尺寸
* ui->tableWidget->setIconSize(QSize(24, 24));
*
* 【关键注意事项】
* 1. 尺寸控制:图标显示尺寸由QTableWidget::setIconSize()全局控制,单个单元格无法单独设置;
* 2. 资源路径:使用资源文件时需确保路径正确(以:/开头),本地图片需传入完整路径;
* 3. 透明适配:QIcon自动适配单元格选中/未选中状态,也可通过QIcon::addPixmap()自定义状态图标。
*/
/**
* @fn void QTableWidgetItem::setSelected(bool selected)
* @brief 设置单元格是否被选中
* @details 控制单元格的选中状态,选中的单元格会按照系统/自定义样式高亮显示;
* 选中效果受QTableWidget的选择模式(setSelectionMode)控制。
*
* @参数说明:
* @param selected - bool类型,true=选中单元格,false=取消选中(默认)。
*
* @使用示例:
* // 1. 设置表格为单选模式,选中指定单元格
* ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
* QTableWidgetItem* item1 = new QTableWidgetItem("选中单元格");
* item1->setSelected(true);
* ui->tableWidget->setItem(3, 0, item1);
*
* // 2. 多选模式下选中多个单元格
* ui->tableWidget->setSelectionMode(QAbstractItemView::MultiSelection);
* QTableWidgetItem* item2 = ui->tableWidget->item(3, 1);
* if (item2) item2->setSelected(true);
*
* 【关键注意事项】
* 1. 选择模式:仅在非"NoSelection"模式下,选中状态才会生效;
* 2. 信号触发:调用setSelected()会触发QTableWidget::itemSelectionChanged()信号;
* 3. 视觉样式:选中高亮样式可通过QSS自定义(如QTableWidget::item:selected);
* 4. 整行/列选中:若表格开启setSelectionBehavior(QAbstractItemView::SelectRows),选中单元格会同步选中整行。
*/
/**
* @fn void QTableWidgetItem::setSizeHint(const QSize& size)
* @brief 设置单元格的尺寸提示(自定义单元格大小)
* @details 为单个单元格设置固定尺寸,优先级高于QTableWidget的默认单元格尺寸;
* 未设置时,单元格尺寸由内容(文本+图标)和表格列宽/行高自动计算。
* @note 注:方法名正确为setSizeHint(非setSizeHints),Qt官方无setSizeHints方法,此处为笔误修正。
*
* @参数说明:
* @param size - QSize类型,width为单元格宽度,height为单元格高度(单位:像素)。
*
* @使用示例:
* // 设置单元格固定尺寸(宽150px,高40px)
* QTableWidgetItem* item = new QTableWidgetItem("自定义尺寸");
* item->setSizeHint(QSize(150, 40));
* ui->tableWidget->setItem(4, 0, item);
*
* 【关键注意事项】
* 1. 行列适配:单元格宽度受表格列宽限制(若列宽<size.width(),则按列宽显示);
* 2. 统一尺寸:若表格设置setUniformRowHeights(true),行高会统一,单元格高度设置失效;
* 3. 最小尺寸:设置的尺寸小于内容最小显示尺寸时,自动适配为内容最小尺寸。
*/
/**
* @fn void QTableWidgetItem::setFont(const QFont& font)
* @brief 设置单元格文本的字体样式
* @details 自定义单个单元格的字体(大小、粗细、字体家族、颜色等),优先级高于QTableWidget的全局字体设置;
* 未单独设置时,继承表格的全局字体样式。
*
* @参数说明:
* @param font - QFont类型,包含字体家族、大小、粗细、下划线等样式属性。
*
* @使用示例:
* // 设置单元格字体(微软雅黑、14号、粗体)
* QTableWidgetItem* item = new QTableWidgetItem("自定义字体");
* QFont font("Microsoft YaHei", 14, QFont::Bold);
* item->setFont(font);
* // 额外设置文本颜色(QFont不包含颜色,需通过setForeground)
* item->setForeground(Qt::blue);
* ui->tableWidget->setItem(4, 1, item);
*
* 【关键注意事项】
* 1. 颜色独立:QFont仅控制字体样式(大小/粗细/家族),文本颜色需通过setForeground()设置;
* 2. 优先级:单个单元格字体 > 表格全局字体 > 应用程序默认字体;
* 3. 动态生效:设置后立即刷新单元格视觉效果,无需额外刷新表格。
*/
}
Widget::~Widget()
{
delete ui;
}
第三章 QTableWidget 核心方法详解
讲完了 QTableWidgetItem 类,我们接下来讲 QTableWidget 的核心方法 ------ 这是操作表格单元格、行列、表头最核心的接口。我们讲:item、setItem、currentItem、currentRow、currentColumn、row、column、rowCount、columnCount、insertRow、insertColumn、removeRow、removeColumn、setHorizontalHeaderItem、setVerticalHeaderItem。
3.1 方法一:item ()------ 按行号 + 列号精准获取指定单元格
3.1.1 方法的核心定义
item() 是 QTableWidget 最核心、最常用 的单元格查询方法 ------ 它按 "行号 + 列号" 精准定位,返回表格中 "第 row 行、第 column 列" 对应的 QTableWidgetItem 指针;行 / 列号超出有效范围或该位置无单元格时,返回 nullptr。
通俗理解:item() 就像 "按坐标找格子"------ 你告诉它 "第几行、第几列",它就把那个小格子拿给你;如果坐标不对,或者那个格子是空的,它就拿个空的给你(返回 nullptr)。
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 行 / 列规则(超级重要!) :
- 行号、列号均从 0 开始;
- 有效范围:
0 ≤ row < rowCount(),0 ≤ column < columnCount();
- 判空强制!(超级重要!说三遍!) :
- 未设置单元格的位置会返回
nullptr; - 必须先判空再操作! 直接操作会导致程序崩溃!
- 未设置单元格的位置会返回
- 只读指针(超级重要!) :
- 返回的指针可修改单元格属性(如
setText); - 但不可手动 delete !需通过
removeRow/removeColumn移除,或由表格自动管理!
- 返回的指针可修改单元格属性(如
3.1.2 关联 API 详解(逐词逐句,零模糊)
1. 按行号 + 列号获取指定单元格:QTableWidgetItem* item (int row, int column) const
函数原型:
QTableWidgetItem* QTableWidget::item(int row, int column) const;
逐词逐句底层解析:
QTableWidgetItem*:返回值类型,返回单元格指针;QTableWidget:::成员函数;item():函数名,"获取单元格" 的意思;int row:入参,目标单元格的行号;int column:入参,目标单元格的列号;const:常成员函数。
参数说明:
row:目标单元格的行号,int类型,从 0 开始;column:目标单元格的列号,int类型,从 0 开始。
返回值说明:
- 返回
QTableWidgetItem*类型的指针; - 行 / 列有效且该位置有单元格 → 返回对应指针;
- 行 / 列无效或该位置无单元格 → 返回
nullptr; - 必须先判空再操作!
3.1.3 使用示例
#include <QTableWidgetItem>
#include <QDebug>
// 假设表格已经设置了 3 行 3 列,并填充了数据
// 获取第 2 行(索引 1)、第 3 列(索引 2)的单元格
QTableWidgetItem* targetItem = ui->tableWidget->item(1, 2);
if (targetItem != nullptr) { // 必须判空!
qDebug() << "单元格文本:" << targetItem->text();
// 修改文本
targetItem->setText("已修改");
} else {
qDebug() << "该位置无单元格";
}
3.1.4 关键注意事项(必知!)
- 行 / 列从 0 开始!(超级重要!);
- 判空强制!(超级重要!说三遍!):必须先判空再操作!
- 不可手动 delete 返回的指针!(超级重要!):需通过 removeRow/removeColumn 移除!
3.2 方法二:setItem ()------ 按行号 + 列号设置指定位置的单元格
3.2.1 方法的核心定义
setItem() 是 QTableWidget 最核心、最常用的单元格设置方法 ------ 它将自定义的 QTableWidgetItem 对象绑定到表格的 "第 row 行、第 column 列" 位置;若该位置已有单元格,会被新单元格覆盖。
注意! 你提供的资料里写的参数类型是 QTableWidget*,这是一个严重的笔误!正确的参数类型是 QTableWidgetItem*,这里我们修正过来。
通俗理解:setItem() 就像 "把一个准备好的小格子放到表格的指定位置"------ 你告诉它 "放到第几行、第几列",它就把小格子放进去;如果那个位置已经有小格子了,新的就会把旧的换掉。
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 开篇的注意事项再强调一遍!(超级重要!) :
- 在插入条目之前,必须先指明表格的行列数量才行!
- 可以用
setRowCount()/setColumnCount()设置,也可以用insertRow()/insertColumn()插入; - 否则,设置的单元格可能无效,界面上看不到!
- 内存管理!(超级重要!说三遍!) :
- 设置新单元格后,原单元格不会自动释放 ,需手动
delete避免内存泄漏(如delete ui->tableWidget->item(row, column)); - 新单元格的所有权移交至表格,无需手动
delete(移除时用removeRow/removeColumn);
- 设置新单元格后,原单元格不会自动释放 ,需手动
- 行 / 列范围(超级重要!) :
- 行 / 列号超出当前表格范围时,需先插入对应行列(
insertRow/insertColumn),否则设置无效;
- 行 / 列号超出当前表格范围时,需先插入对应行列(
- 空值处理 :传入
nullptr则清空该位置单元格。
3.2.2 关联 API 详解(逐词逐句,零模糊)
1. 按行号 + 列号设置指定位置的单元格:void setItem (int row, int column, QTableWidgetItem* item)
函数原型:
void QTableWidget::setItem(int row, int column, QTableWidgetItem* item);
逐词逐句底层解析:
void:无返回值;QTableWidget:::成员函数;setItem():函数名,"设置单元格" 的意思;int row:入参,目标位置的行号;int column:入参,目标位置的列号;QTableWidgetItem* item:入参,要设置的单元格对象指针。
参数说明:
row:目标位置的行号,int类型,从 0 开始;column:目标位置的列号,int类型,从 0 开始;item:要设置的单元格对象指针,QTableWidgetItem*类型;- 必须是
new出来的堆对象; - 传入
nullptr则清空该位置单元格。
- 必须是
3.2.3 使用示例
#include <QTableWidgetItem>
// 【必须!】第一步:先设置表格的行列数量!
ui->tableWidget->setRowCount(2); // 2 行
ui->tableWidget->setColumnCount(2); // 2 列
// 第二步:设置单元格
// 示例1:为第 1 行第 1 列(索引 0,0)设置普通文本单元格
QTableWidgetItem* cellItem = new QTableWidgetItem("表格单元格");
ui->tableWidget->setItem(0, 0, cellItem);
// 示例2:为第 1 行第 2 列(索引 0,1)设置带图标的单元格
QTableWidgetItem* iconItem = new QTableWidgetItem("带图标单元格");
iconItem->setIcon(QIcon(":/images/icon.png"));
ui->tableWidget->setItem(0, 1, iconItem);
3.2.4 关键注意事项(必知!)
- 必须先设置表格的行列数量!(超级重要!开篇就讲!);
- 内存管理!(超级重要!说三遍!):设置新单元格前,原单元格需手动 delete!新单元格所有权移交表格!
- 行 / 列范围(超级重要!):超出范围需先插入行列!
- 参数类型修正:是 QTableWidgetItem*,不是 QTableWidget*!
3.3 方法三:currentItem ()------ 获取当前选中的单元格对象
3.3.1 方法的核心定义
currentItem() 是 QTableWidget 用于获取当前选中单元格对象指针 的核心方法 ------ 无选中单元格 / 表格为空时返回 nullptr,是操作选中单元格属性的核心入口。
通俗理解:currentItem() 就像 "拿到表格上当前被标亮的那个小格子"------ 拿到后你就可以读它、改它;如果没有任何格子被标亮,或者表格是空的,你就拿不到(返回 nullptr)。
这里有几个超级重要的规则,必须牢记:
- 判空必须!(超级重要!说三遍!) :
- 无选中单元格 / 表格为空时返回
nullptr; - 必须先判空再操作! 直接操作会导致程序崩溃!
- 无选中单元格 / 表格为空时返回
- 受选择模式影响 :若表格设为
NoSelection(无选择),始终返回nullptr; - 联动查询 :可结合
currentRow()/currentColumn()快速获取选中单元格的位置。
3.3.2 使用示例
#include <QTableWidgetItem>
#include <QDebug>
// 获取选中单元格并操作(必须先判空!)
QTableWidgetItem* selectedItem = ui->tableWidget->currentItem();
if (selectedItem != nullptr) { // 判空!判空!判空!
qDebug() << "当前选中单元格文本:" << selectedItem->text();
selectedItem->setText("已选中:" + selectedItem->text());
} else {
qDebug() << "当前无选中单元格";
}
3.4 方法四:currentRow ()------ 获取当前选中单元格所属的行号
3.4.1 方法的核心定义
currentRow() 是 QTableWidget 用于获取当前选中单元格所属行号的方法 ------ 行号从 0 开始;无选中单元格时返回 -1。
通俗理解:currentRow() 就像 "问表格:'当前被标亮的格子在第几行呀?'"------ 它会告诉你行号,从 0 开始;如果没有被标亮的格子,它就说 -1。
关键注意事项:
- 行号从 0 开始!(超级重要!):用户视角展示需 +1;
- 联动关系 :
currentRow()=currentItem()->row()(currentItem不为nullptr时); - 整行选中 :若表格开启
setSelectionBehavior(SelectRows),选中任意单元格均返回该行号。
3.4.2 使用示例
#include <QDebug>
// 打印当前选中单元格的行号和列号
int selRow = ui->tableWidget->currentRow();
int selCol = ui->tableWidget->currentColumn();
if (selRow != -1 && selCol != -1) {
qDebug() << "选中位置:第" << selRow+1 << "行,第" << selCol+1 << "列";
} else {
qDebug() << "无选中单元格";
}
3.5 方法五:currentColumn ()------ 获取当前选中单元格所属的列号
这个方法和 currentRow() 几乎一模一样,只是返回的是列号,我们简单回顾一下。
关键注意事项:
- 列号从 0 开始!(超级重要!):用户视角展示需 +1;
- 联动关系 :
currentColumn()=currentItem()->column()(currentItem不为nullptr时); - 整列选中 :若表格开启
setSelectionBehavior(SelectColumns),选中任意单元格均返回该列号。
3.6 方法六:row ()------ 根据单元格对象获取其所属的行号
这个方法我们在讲 QTableWidgetItem::row () 时已经提到过,它和 item->row() 是等价的,结果完全一致。
通俗理解:table->row(item) 就像 "你拿着一个小格子问表格:'这个格子在你这里的第几行呀?'"------ 和直接问格子自己是一样的。
3.7 方法七:column ()------ 根据单元格对象获取其所属的列号
这个方法和 table->row(item) 几乎一模一样,只是返回的是列号,它和 item->column() 是等价的。
3.8 方法八:rowCount ()------ 获取表格当前的总行数
3.8.1 方法的核心定义
rowCount() 是 QTableWidget 用于获取表格当前总行数的结构查询方法 ------ 返回表格中已存在的行总数(包含空行),默认值为 0(空表格)。
通俗理解:rowCount() 就像 "数一数表格里一共有多少行"------ 哪怕某一行是空的,没有任何单元格,也算一行。
关键注意事项:
- 实时更新 :插入 / 删除行(
insertRow/removeRow)后,rowCount()立即更新; - 空行计数:即使行内无单元格(空行),仍计入总行数;
- 遍历边界 :遍历行时,循环上限为
rowCount()-1。
3.8.2 使用示例
#include <QTableWidgetItem>
#include <QDebug>
// 遍历表格所有行
int totalRows = ui->tableWidget->rowCount();
for (int r = 0; r < totalRows; ++r) {
// 处理每行数据,比如获取每行第一列的文本
QTableWidgetItem* firstCell = ui->tableWidget->item(r, 0);
if (firstCell != nullptr) {
qDebug() << "第" << r+1 << "行首列文本:" << firstCell->text();
}
}
3.9 方法九:columnCount ()------ 获取表格当前的总列数
这个方法和 rowCount() 几乎一模一样,只是返回的是总列数,我们简单回顾一下。
关键注意事项:
- 实时更新 :插入 / 删除列(
insertColumn/removeColumn)后,columnCount()立即更新; - 空列计数:即使列内无单元格(空列),仍计入总列数;
- 遍历边界 :遍历列时,循环上限为
columnCount()-1。
3.10 方法十:insertRow ()------ 在指定行号位置插入新行
3.10.1 方法的核心定义
insertRow() 是 QTableWidget 用于扩展表格行数 的方法 ------ 它在第 row 行位置插入一行空行;row 超出当前行号范围时,自动追加到表格末尾。
通俗理解:insertRow() 就像 "在表格的指定位置插入一行新的空白行"------ 比如在第 2 行(行号 1)前面插一行,原来的第 2 行及后面的行都会自动往后挪一位。
这里有几个超级重要的规则,必须牢记:
- 行号容错(超级重要!) :
row < 0→ 插入到开头(行号 0);row > rowCount()→ 追加到末尾(等价于在最后添加一行);- 不用担心行号超出范围,Qt 会自动适配!
- 行号偏移(超级重要!) :
- 插入位置后的行号自动 +1;
- 比如在索引 1 插入,原索引 1 行变为索引 2,原索引 2 变为索引 3,以此类推;
- 空行特性 :插入的新行为空行,需手动调用
setItem()设置单元格。
3.10.2 使用示例
#include <QTableWidgetItem>
// 示例1:在第 1 行(索引 0)插入新行
ui->tableWidget->insertRow(0);
// 为新插入的行设置单元格
QTableWidgetItem* newItem = new QTableWidgetItem("新行首列");
ui->tableWidget->setItem(0, 0, newItem);
// 示例2:在表格末尾插入新行(常用!)
int lastRow = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(lastRow);
3.11 方法十一:insertColumn ()------ 在指定列号位置插入新列
这个方法和 insertRow() 几乎一模一样,只是操作的是列,我们简单回顾一下。
关键注意事项:
- 列号容错(超级重要!) :
column < 0→ 插入到开头(列号 0);column > columnCount()→ 追加到末尾;
- 列号偏移(超级重要!) :
- 插入位置后的列号自动 +1;
- 空列特性 :插入的新列为空列,需手动调用
setItem()设置单元格。
3.12 方法十二:removeRow ()------ 删除指定行号的整行
3.12.1 方法的核心定义
removeRow() 是 QTableWidget 用于删除表格整行 的方法 ------ 它删除第 row 行的所有单元格并移除该行;row 超出有效范围时无操作。
通俗理解:removeRow() 就像 "把表格的指定行整行撕掉"------ 撕掉后,这一行的所有小格子都会被扔掉(自动释放内存),后面的行会自动往前挪填补位置。
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 内存释放!(超级重要!说三遍!) :
- 删除行时,该行所有 QTableWidgetItem 会被自动释放!
- 无需手动 delete !不要去
delete该行的单元格! - 这点和 QListWidget 的
takeItem()不一样!
- 行号偏移(超级重要!) :
- 删除位置后的行号自动 -1;
- 比如删除索引 1 行,原索引 2 行变为索引 1,原索引 3 变为索引 2,以此类推;
- 选中状态(超级重要!) :
- 若删除的是选中行,
currentRow()变为 -1,取消选中。
- 若删除的是选中行,
3.12.2 使用示例
// 示例1:删除表格第 2 行(索引 1)
if (ui->tableWidget->rowCount() > 1) { // 确保行号有效
ui->tableWidget->removeRow(1);
}
// 示例2:删除表格最后一行(常用!)
if (ui->tableWidget->rowCount() > 0) {
int lastRow = ui->tableWidget->rowCount() - 1;
ui->tableWidget->removeRow(lastRow);
}
3.13 方法十三:removeColumn ()------ 删除指定列号的整列
这个方法和 removeRow() 几乎一模一样,只是操作的是列,我们简单回顾一下。
关键注意事项:
- 内存释放!(超级重要!):删除列时,该列所有 QTableWidgetItem 会被自动释放,无需手动 delete!
- 列号偏移(超级重要!):删除位置后的列号自动 -1;
- 选中状态(超级重要!) :若删除的是选中列,
currentColumn()变为 -1,取消选中。
3.14 方法十四:setHorizontalHeaderItem ()------ 设置水平表头(列标题)
3.14.1 方法的核心定义
setHorizontalHeaderItem() 是 QTableWidget 用于 ** 定制水平表头(列标题)** 的方法 ------ 它为第 column 列的水平表头设置自定义条目(文本 / 图标 / 字体);水平表头默认显示列号(1, 2, 3...),设置后替换为自定义内容。
通俗理解:setHorizontalHeaderItem() 就像 "给表格的每一列起个名字"------ 比如第一列叫 "姓名",第二列叫 "年龄",第三列叫 "学号";这些名字显示在表格的最上方。
这里有几个超级重要的规则,必须牢记:
- 列存在性(超级重要!) :
column需小于columnCount(),否则需先调用insertColumn()创建列;- 或者先设置好
columnCount()再设置表头;
- 内存管理 :
item所有权移交至表格,无需手动delete; - 样式定制 :可通过
item的setFont/setIcon/setTextAlignment定制表头样式。
3.14.2 使用示例
#include <QTableWidgetItem>
#include <QFont>
#include <QStringList>
// 【必须!】先设置表格列数(或者先插入列)
ui->tableWidget->setColumnCount(3); // 3 列
// 设置水平表头(列标题)
QStringList headers = {"姓名", "年龄", "性别"};
for (int c = 0; c < headers.size(); ++c) {
QTableWidgetItem* headerItem = new QTableWidgetItem(headers[c]);
// 可选:设置表头字体加粗、居中
headerItem->setFont(QFont("微软雅黑", 12, QFont::Bold));
headerItem->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setHorizontalHeaderItem(c, headerItem);
}
3.15 方法十五:setVerticalHeaderItem ()------ 设置垂直表头(行标题)
这个方法和 setHorizontalHeaderItem() 几乎一模一样,只是操作的是垂直表头(行标题),显示在表格的最左侧,默认显示行号(1, 2, 3...)。
关键注意事项:
- 行存在性(超级重要!) :
row需小于rowCount(),否则需先调用insertRow()创建行; - 内存管理 :
item所有权移交至表格,无需手动delete; - 隐藏表头 :可通过
setVerticalHeaderHidden(true)隐藏垂直表头,通过setHorizontalHeaderHidden(true)隐藏水平表头。
示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QTableWidget>
#include <QTableWidgetItem>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//OK,那么本文件我们就来学习一下QTableWidget的核心方法,这个还是很关键的
//无论是添加还是删除条目,都是在这其中
//而且由于这是二维的了,我们我们不仅要指定行,还得指定列哦~~~
//新增的方法名字叫做setItem~~~
//注意,都是从0开始计数的哦,虽然qt对外显示是从1开始,但是我们要指定行列什么的,
//就是从0开始计数的哦~~~~
//其实还是比较简单的~~~
/**
* @class QTableWidget
* @brief Qt中用于展示二维表格的可视化控件,基于QTableWidgetItem管理单元格、行列、表头
* @details QTableWidget以"行+列"二维结构组织单元格(QTableWidgetItem),提供单元格/行列的增删改查、选中状态查询、表头定制等核心功能;
* 支持精准定位单元格、动态插入/删除行列、自定义表头样式,是Qt中最常用的表格展示与交互控件之一。
*
* 【核心特征】
* 1. 单元格管理:支持按行/列号精准获取/设置单元格,查询选中单元格的位置与对象;
* 2. 行列管理:支持获取行列总数、插入/删除指定行列,动态调整表格结构;
* 3. 表头定制:支持自定义水平(列)/垂直(行)表头的显示内容;
* 4. 选中查询:支持获取当前选中单元格的对象、行号、列号,适配表格交互场景。
*/
// ============================== 核心方法详解 ==============================
/**
* @fn QTableWidgetItem* QTableWidget::item(int row, int column) const
* @brief 按行号+列号精准获取指定单元格的条目指针
* @details 核心单元格查询方法,返回表格中"第row行、第column列"对应的QTableWidgetItem指针;
* 行/列号超出有效范围或该位置无单元格时,返回nullptr。
*
* @参数说明:
* @param row - int类型,目标单元格的行号(从0开始计数);
* @param column - int类型,目标单元格的列号(从0开始计数)。
*
* @返回值说明:
* @return QTableWidgetItem* - 指定位置的单元格指针(行/列无效/无单元格返回nullptr)。
*
* @使用示例:
* // 获取第2行(索引1)、第3列(索引2)的单元格
* QTableWidgetItem* targetItem = ui->tableWidget->item(1, 2);
* if (targetItem) { // 必须判空,避免空指针崩溃
* qDebug() << "单元格文本:" << targetItem->text();
* }
*
* 【关键注意事项】
* 1. 行/列规则:行号、列号均从0开始,有效范围为[0, rowCount()-1]、[0, columnCount()-1];
* 2. 判空强制:未设置单元格的位置会返回nullptr,直接操作会导致程序崩溃;
* 3. 只读指针:返回的指针可修改单元格属性(如setText),但不可手动delete(需通过removeRow/removeColumn移除)。
*/
/**
* @fn void QTableWidget::setItem(int row, int column, QTableWidgetItem* item)
* @brief 按行号+列号设置表格中指定位置的单元格
* @details 核心单元格设置方法,将自定义的QTableWidgetItem对象绑定到表格的"第row行、第column列"位置;
* 若该位置已有单元格,会被新单元格覆盖(原单元格需手动释放内存避免泄漏)。
* @note 注:方法参数正确类型为QTableWidgetItem*(非QTableWidget*),此处修正笔误。
*
* @参数说明:
* @param row - int类型,目标位置的行号(从0开始计数);
* @param column - int类型,目标位置的列号(从0开始计数);
* @param item - QTableWidgetItem*类型,要设置的单元格对象(nullptr则清空该位置单元格)。
*
* @使用示例:
* // 1. 为第1行第1列设置普通文本单元格
* QTableWidgetItem* cellItem = new QTableWidgetItem("表格单元格");
* ui->tableWidget->setItem(0, 0, cellItem);
*
* // 2. 为第1行第2列设置带图标的单元格
* QTableWidgetItem* iconItem = new QTableWidgetItem("带图标单元格");
* iconItem->setIcon(QIcon(":/images/icon.png"));
* ui->tableWidget->setItem(0, 1, iconItem);
*
* 【关键注意事项】
* 1. 内存管理:设置新单元格后,原单元格不会自动释放,需手动delete(如delete ui->tableWidget->item(row, column));
* 2. 行/列范围:行/列号超出当前表格范围时,需先插入对应行列(insertRow/insertColumn),否则设置无效;
* 3. 所有权移交:item的所有权移交至表格,无需手动delete(移除时用removeRow/removeColumn)。
*/
/**
* @fn QTableWidgetItem* QTableWidget::currentItem() const
* @brief 获取当前**选中**的单元格条目指针
* @details 核心选中状态查询方法,返回表格中当前激活选中的单元格指针;无选中单元格/表格为空时返回nullptr。
*
* @返回值说明:
* @return QTableWidgetItem* - 当前选中单元格指针(无选中返回nullptr)。
*
* @使用示例:
* // 获取选中单元格并修改其文本
* QTableWidgetItem* selectedItem = ui->tableWidget->currentItem();
* if (selectedItem) {
* selectedItem->setText("已选中:" + selectedItem->text());
* }
*
* 【关键注意事项】
* 1. 判空必须:无选中单元格时返回nullptr,直接操作会导致崩溃;
* 2. 选中模式:受表格选择模式(setSelectionMode)影响,无选择权限时始终返回nullptr;
* 3. 联动查询:可结合currentRow()/currentColumn()快速获取选中单元格的位置。
*/
/**
* @fn int QTableWidget::currentRow() const
* @brief 获取当前**选中**单元格所属的行号
* @details 选中位置查询方法,返回当前选中单元格的行号(从0开始);无选中单元格时返回-1。
*
* @返回值说明:
* @return int - 选中单元格行号(0开始,无选中返回-1)。
*
* @使用示例:
* // 打印当前选中单元格的行号和列号
* int selRow = ui->tableWidget->currentRow();
* int selCol = ui->tableWidget->currentColumn();
* if (selRow != -1 && selCol != -1) {
* qDebug() << "选中位置:第" << selRow+1 << "行,第" << selCol+1 << "列";
* } else {
* qDebug() << "无选中单元格";
* }
*
* 【关键注意事项】
* 1. 行号规则:行号从0开始,用户视角展示需+1;
* 2. 联动关系:currentRow() = currentItem()->row()(currentItem不为nullptr时);
* 3. 整行选中:若表格开启整行选中(setSelectionBehavior(SelectRows)),选中任意单元格均返回该行号。
*/
/**
* @fn int QTableWidget::currentColumn() const
* @brief 获取当前**选中**单元格所属的列号
* @details 选中位置查询方法,返回当前选中单元格的列号(从0开始);无选中单元格时返回-1。
*
* @返回值说明:
* @return int - 选中单元格列号(0开始,无选中返回-1)。
*
* @使用示例:
* // 验证选中单元格的列号是否为目标列
* if (ui->tableWidget->currentColumn() == 2) {
* qDebug() << "选中了第3列单元格";
* }
*
* 【关键注意事项】
* 1. 列号规则:列号从0开始,用户视角展示需+1;
* 2. 联动关系:currentColumn() = currentItem()->column()(currentItem不为nullptr时);
* 3. 整列选中:若表格开启整列选中(setSelectionBehavior(SelectColumns)),选中任意单元格均返回该列号。
*/
/**
* @fn int QTableWidget::row(QTableWidgetItem* item) const
* @brief 根据单元格对象获取其所属的**行号**
* @details 反向位置查询方法,返回指定单元格在表格中的行号;item为nullptr或未加入表格时返回-1。
*
* @参数说明:
* @param item - QTableWidgetItem*类型,目标单元格对象指针。
*
* @返回值说明:
* @return int - 单元格行号(0开始,无效item返回-1)。
*
* @使用示例:
* // 获取指定单元格的行/列号
* QTableWidgetItem* targetItem = ui->tableWidget->item(1, 2);
* if (targetItem) {
* int row = ui->tableWidget->row(targetItem);
* int col = ui->tableWidget->column(targetItem);
* qDebug() << "单元格位置:行" << row << ",列" << col;
* }
*
* 【关键注意事项】
* 1. 等价性:table->row(item) 等价于 item->row(),二者结果一致;
* 2. 无效判断:item为nullptr或未通过setItem()加入表格时,返回-1;
* 3. 动态更新:单元格行号随表格行增删自动更新,该方法返回实时行号。
*/
/**
* @fn int QTableWidget::column(QTableWidgetItem* item) const
* @brief 根据单元格对象获取其所属的**列号**
* @details 反向位置查询方法,返回指定单元格在表格中的列号;item为nullptr或未加入表格时返回-1。
*
* @参数说明:
* @param item - QTableWidgetItem*类型,目标单元格对象指针。
*
* @返回值说明:
* @return int - 单元格列号(0开始,无效item返回-1)。
*
* @使用示例:
* // 遍历表格所有单元格,打印非空单元格的位置
* for (int r = 0; r < ui->tableWidget->rowCount(); ++r) {
* for (int c = 0; c < ui->tableWidget->columnCount(); ++c) {
* QTableWidgetItem* item = ui->tableWidget->item(r, c);
* if (item) {
* int row = ui->tableWidget->row(item);
* int col = ui->tableWidget->column(item);
* qDebug() << "非空单元格:行" << row << "列" << col << ",文本:" << item->text();
* }
* }
* }
*
* 【关键注意事项】
* 1. 等价性:table->column(item) 等价于 item->column(),二者结果一致;
* 2. 无效判断:item为nullptr或未加入表格时,返回-1;
* 3. 动态更新:单元格列号随表格列增删自动更新,该方法返回实时列号。
*/
/**
* @fn int QTableWidget::rowCount() const
* @brief 获取表格当前的**总行数**
* @details 表格结构查询方法,返回表格中已存在的行总数(包含空行),默认值为0(空表格)。
*
* @返回值说明:
* @return int - 表格总行数(≥0)。
*
* @使用示例:
* // 遍历表格所有行
* int totalRows = ui->tableWidget->rowCount();
* for (int r = 0; r < totalRows; ++r) {
* // 处理每行数据
* QTableWidgetItem* firstCell = ui->tableWidget->item(r, 0);
* if (firstCell) qDebug() << "第" << r+1 << "行首列文本:" << firstCell->text();
* }
*
* 【关键注意事项】
* 1. 实时更新:插入/删除行(insertRow/removeRow)后,rowCount()立即更新;
* 2. 空行计数:即使行内无单元格(空行),仍计入总行数;
* 3. 遍历边界:遍历行时,循环上限为rowCount()-1。
*/
/**
* @fn int QTableWidget::columnCount() const
* @brief 获取表格当前的**总列数**
* @details 表格结构查询方法,返回表格中已存在的列总数(包含空列),默认值为0(空表格)。
*
* @返回值说明:
* @return int - 表格总列数(≥0)。
*
* @使用示例:
* // 检查表格列数是否满足需求
* if (ui->tableWidget->columnCount() < 3) {
* // 补充列至3列
* int needAdd = 3 - ui->tableWidget->columnCount();
* for (int i = 0; i < needAdd; ++i) {
* ui->tableWidget->insertColumn(ui->tableWidget->columnCount());
* }
* }
*
* 【关键注意事项】
* 1. 实时更新:插入/删除列(insertColumn/removeColumn)后,columnCount()立即更新;
* 2. 空列计数:即使列内无单元格(空列),仍计入总列数;
* 3. 遍历边界:遍历列时,循环上限为columnCount()-1。
*/
/**
* @fn void QTableWidget::insertRow(int row)
* @brief 在表格指定行号位置**插入新行**
* @details 表格行扩展方法,在第row行位置插入一行空行;row超出当前行号范围时,自动追加到表格末尾。
*
* @参数说明:
* @param row - int类型,插入新行的目标位置(从0开始计数)。
*
* @使用示例:
* // 在第1行(索引0)插入新行
* ui->tableWidget->insertRow(0);
* // 为新插入的行设置单元格
* QTableWidgetItem* newItem = new QTableWidgetItem("新行首列");
* ui->tableWidget->setItem(0, 0, newItem);
*
* 【关键注意事项】
* 1. 行号容错:row < 0 → 插入到开头;row > rowCount() → 追加到末尾;
* 2. 行号偏移:插入位置后的行号自动+1(如在索引1插入,原索引1行变为索引2);
* 3. 空行特性:插入的新行为空行,需手动调用setItem()设置单元格。
*/
/**
* @fn void QTableWidget::insertColumn(int column)
* @brief 在表格指定列号位置**插入新列**
* @details 表格列扩展方法,在第column列位置插入一列空列;column超出当前列号范围时,自动追加到表格末尾。
*
* @参数说明:
* @param column - int类型,插入新列的目标位置(从0开始计数)。
*
* @使用示例:
* // 在表格末尾插入新列
* int lastCol = ui->tableWidget->columnCount();
* ui->tableWidget->insertColumn(lastCol);
* // 设置新列的表头
* QTableWidgetItem* headerItem = new QTableWidgetItem("新列表头");
* ui->tableWidget->setHorizontalHeaderItem(lastCol, headerItem);
*
* 【关键注意事项】
* 1. 列号容错:column < 0 → 插入到开头;column > columnCount() → 追加到末尾;
* 2. 列号偏移:插入位置后的列号自动+1(如在索引1插入,原索引1列变为索引2);
* 3. 空列特性:插入的新列为空列,需手动调用setItem()设置单元格。
*/
/**
* @fn void QTableWidget::removeRow(int row)
* @brief 删除表格中指定行号的**整行**
* @details 表格行删除方法,删除第row行的所有单元格并移除该行;row超出有效范围时无操作。
*
* @参数说明:
* @param row - int类型,要删除的行号(从0开始计数)。
*
* @使用示例:
* // 删除表格最后一行
* if (ui->tableWidget->rowCount() > 0) {
* ui->tableWidget->removeRow(ui->tableWidget->rowCount() - 1);
* }
*
* 【关键注意事项】
* 1. 内存释放:删除行时,该行所有QTableWidgetItem会被自动释放,无需手动delete;
* 2. 行号偏移:删除位置后的行号自动-1(如删除索引1行,原索引2行变为索引1);
* 3. 选中状态:若删除的是选中行,currentRow()变为-1,取消选中。
*/
/**
* @fn void QTableWidget::removeColumn(int column)
* @brief 删除表格中指定列号的**整列**
* @details 表格列删除方法,删除第column列的所有单元格并移除该列;column超出有效范围时无操作。
*
* @参数说明:
* @param column - int类型,要删除的列号(从0开始计数)。
*
* @使用示例:
* // 删除表格第一列(索引0)
* if (ui->tableWidget->columnCount() > 0) {
* ui->tableWidget->removeColumn(0);
* }
*
* 【关键注意事项】
* 1. 内存释放:删除列时,该列所有QTableWidgetItem会被自动释放,无需手动delete;
* 2. 列号偏移:删除位置后的列号自动-1(如删除索引1列,原索引2列变为索引1);
* 3. 选中状态:若删除的是选中列,currentColumn()变为-1,取消选中。
*/
/**
* @fn void QTableWidget::setHorizontalHeaderItem(int column, QTableWidgetItem* item)
* @brief 设置表格**水平表头(列标题)** 的指定列条目
* @details 表头定制方法,为第column列的水平表头设置自定义条目(文本/图标/字体);
* 水平表头默认显示列号,设置后替换为自定义内容。
* @note 注:方法参数正确类型为QTableWidgetItem*(非QTableWidget*),此处修正笔误。
*
* @参数说明:
* @param column - int类型,要设置的表头列号(从0开始计数);
* @param item - QTableWidgetItem*类型,表头条目对象(nullptr则清空该列表头)。
*
* @使用示例:
* // 设置水平表头(列标题)
* QStringList headers = {"姓名", "年龄", "性别"};
* for (int c = 0; c < headers.size(); ++c) {
* // 确保列存在
* if (c >= ui->tableWidget->columnCount()) {
* ui->tableWidget->insertColumn(c);
* }
* QTableWidgetItem* headerItem = new QTableWidgetItem(headers[c]);
* headerItem->setFont(QFont("微软雅黑", 12, QFont::Bold)); // 表头字体加粗
* ui->tableWidget->setHorizontalHeaderItem(c, headerItem);
* }
*
* 【关键注意事项】
* 1. 列存在性:column需小于columnCount(),否则需先调用insertColumn()创建列;
* 2. 内存管理:item所有权移交至表格,无需手动delete;
* 3. 样式定制:可通过item的setFont/setIcon/setTextAlignment定制表头样式。
*/
/**
* @fn void QTableWidget::setVerticalHeaderItem(int row, QTableWidgetItem* item)
* @brief 设置表格**垂直表头(行标题)** 的指定行条目
* @details 表头定制方法,为第row行的垂直表头设置自定义条目(文本/图标/字体);
* 垂直表头默认显示行号,设置后替换为自定义内容。
* @note 注:方法参数正确类型为QTableWidgetItem*(非QTableWidget*),此处修正笔误。
*
* @参数说明:
* @param row - int类型,要设置的表头行号(从0开始计数);
* @param item - QTableWidgetItem*类型,表头条目对象(nullptr则清空该行表头)。
*
* @使用示例:
* // 设置垂直表头(行标题)
* for (int r = 0; r < 3; ++r) {
* // 确保行存在
* if (r >= ui->tableWidget->rowCount()) {
* ui->tableWidget->insertRow(r);
* }
* QTableWidgetItem* headerItem = new QTableWidgetItem(QString("行%1").arg(r+1));
* headerItem->setTextAlignment(Qt::AlignCenter); // 表头文本居中
* ui->tableWidget->setVerticalHeaderItem(r, headerItem);
* }
*
* 【关键注意事项】
* 1. 行存在性:row需小于rowCount(),否则需先调用insertRow()创建行;
* 2. 内存管理:item所有权移交至表格,无需手动delete;
* 3. 样式定制:可通过item的setFont/setIcon/setTextAlignment定制表头样式;
* 4. 隐藏表头:可通过setVerticalHeaderHidden(true)隐藏垂直表头。
*/
QTableWidget* tw=new QTableWidget(this);
tw->setGeometry(100,100,300,300);
// 2. 【必须】设置表格的行列数量
//要严格注意,在插入条目之前,必须先指明表格的行列数量才行哦~~~
tw->setRowCount(2); // 2行
tw->setColumnCount(2); // 2列
//然后还有就是,一般在我们设置完表格的行列数量之后
//qt就会自动在表格的上方和左方加上表头,1、2什么的
//要是我们想自定义,那么就得使用上面提到的
//setHorizonalHeaderItem方法和setVerticalHeaderItem方法
//指明是横还是竖的哪一行哪一列,然后进行设置
//注意:从0开始计数
// ================= 设置水平表头 (列标题) =================
// 注意:第二个参数必须是 QTableWidgetItem* 对象
// 第 0 列 表头
QTableWidgetItem* headerItem0 = new QTableWidgetItem("姓名");
// 可选:设置表头文字居中
headerItem0->setTextAlignment(Qt::AlignCenter);
tw->setHorizontalHeaderItem(0, headerItem0);
// 第 1 列 表头
QTableWidgetItem* headerItem1 = new QTableWidgetItem("年龄");
headerItem1->setTextAlignment(Qt::AlignCenter);
tw->setHorizontalHeaderItem(1, headerItem1);
// ================= 设置垂直表头 (行标题) =================
// 如果你想自定义左侧的行号 (默认是 1, 2, 3...)
// 第 0 行 表头
QTableWidgetItem* vHeaderItem0 = new QTableWidgetItem("第一行");
tw->setVerticalHeaderItem(0, vHeaderItem0);
// 第 1 行 表头
QTableWidgetItem* vHeaderItem1 = new QTableWidgetItem("第二行");
tw->setVerticalHeaderItem(1, vHeaderItem1);
// ================= 填充表格内容 =================
QTableWidgetItem* item1 = new QTableWidgetItem("张三");
QTableWidgetItem* item2 = new QTableWidgetItem("18");
QTableWidgetItem* item3 = new QTableWidgetItem("李四");
QTableWidgetItem* item4 = new QTableWidgetItem("20");
// 放入表格,要指定行和列哦~~~
tw->setItem(0, 0, item1);
tw->setItem(0, 1, item2);
tw->setItem(1, 0, item3);
tw->setItem(1, 1, item4);
//我们还可以在指定行那里增加行
//即将原本的那一行往后赶,新增的成为那一行,列也是同理~~~
}
Widget::~Widget()
{
delete ui;
}
第四章 QTableWidget 核心交互信号详解
讲完了所有核心方法,我们最后来讲 QTableWidget 的核心交互信号------ 这是表格与业务逻辑联动的核心桥梁,覆盖点击、双击、鼠标悬浮、选中变更等场景。
按照你提供的顺序,我们讲:cellClicked、cellDoubleClicked、cellEntered、currentCellChanged。
4.1 信号一:cellClicked (int row, int column)------ 用户鼠标单击单元格时触发
4.1.1 信号的核心定义
cellClicked 是 QTableWidget 纯交互触发 的信号 ------ 它仅响应用户鼠标单击单元格操作,代码选中单元格不触发,参数返回被点击单元格的行 / 列号(从 0 开始)。
通俗理解:cellClicked 就像 "用户用鼠标点了表格里的某个小格子时通知你"------ 它会告诉你 "点的是第几行、第几列";只响应用户的点击,你用代码选中格子它不会通知你。
这里有几个超级重要的规则,必须牢记:
- 触发条件(超级重要!) :
- 仅用户单击单元格触发;
- 代码调用
setCurrentCell()/setCurrentItem()不触发; - 这点和
currentCellChanged不一样!
- 参数有效性(超级重要!) :
row/column始终为有效范围(0 ≤ row < rowCount(),0 ≤ column < columnCount());- 点击表格空白处(无单元格区域)不触发此信号;
- 无需额外校验参数有效性!
- 选中联动(超级重要!) :
- 单击单元格会自动将其设为当前选中单元格;
- 因此会先触发
cellClicked(),再触发currentCellChanged();
- 重复点击同一条目也触发(超级重要!) :
- 哪怕单元格已经是选中项,再次点击也会触发
cellClicked()! - 这点和
currentCellChanged不一样!
- 哪怕单元格已经是选中项,再次点击也会触发
4.1.2 信号参数详解
信号原型:
void QTableWidget::cellClicked(int row, int column);
参数说明:
row:int类型,被点击单元格的行号(从 0 开始);column:int类型,被点击单元格的列号(从 0 开始)。
4.1.3 使用示例
#include <QTableWidgetItem>
#include <QDebug>
// 绑定信号(用 Lambda 表达式)
connect(ui->tableWidget, &QTableWidget::cellClicked,
this, [=](int row, int col){
qDebug() << "单击单元格:第" << row+1 << "行,第" << col+1 << "列";
// 获取该单元格并修改文本
QTableWidgetItem* item = ui->tableWidget->item(row, col);
if (item != nullptr) {
item->setText("已单击");
}
});
4.2 信号二:cellDoubleClicked (int row, int column)------ 用户鼠标双击单元格时触发
4.2.1 信号的核心定义
cellDoubleClicked 是 QTableWidget 适配 "双击单元格执行核心操作" 场景的信号 ------ 它仅响应用户鼠标双击操作,代码操作不触发,参数返回被双击单元格的行 / 列号。
通俗理解:cellDoubleClicked 就像 "用户用鼠标快速双击了表格里的某个小格子时通知你"------ 它适合做 "编辑单元格""打开详情""查看关联数据" 这种需要双击确认的操作。
这里有几个超级重要的规则,必须牢记:
- 触发顺序(超级重要!) :
- 双击会先触发
cellClicked()(第一次单击),再触发此信号; - 如果你同时绑定了这两个信号,要注意逻辑冲突!
- 双击会先触发
- 触发条件(超级重要!) :
- 仅用户双击触发;
- 代码操作 / 单击均不触发;
- 参数有效性 :
row/column始终为有效范围,无需额外校验。
4.2.2 使用示例
#include <QTableWidgetItem>
#include <QInputDialog>
#include <QLineEdit>
// 绑定信号(用 Lambda 表达式)
connect(ui->tableWidget, &QTableWidget::cellDoubleClicked,
this, [=](int row, int col){
// 获取该单元格
QTableWidgetItem* item = ui->tableWidget->item(row, col);
if (item == nullptr) {
// 无单元格时创建新单元格
item = new QTableWidgetItem();
ui->tableWidget->setItem(row, col, item);
}
// 弹出输入框编辑文本
QString newText = QInputDialog::getText(this, "编辑单元格",
"修改内容:",
QLineEdit::Normal,
item->text());
if (!newText.isEmpty()) {
item->setText(newText);
}
});
4.3 信号三:cellEntered (int row, int column)------ 鼠标光标进入单元格时触发
4.3.1 信号的核心定义
cellEntered 是 QTableWidget 用于鼠标悬浮交互 的信号 ------ 它在鼠标光标进入单元格区域时触发,需开启鼠标跟踪才会触发!
通俗理解:cellEntered 就像 "鼠标移到表格里的某个小格子上时通知你"------ 你可以用它做 "鼠标悬浮高亮单元格""显示 Tooltip 提示" 等效果;但注意,你必须先开启鼠标跟踪,否则它不会通知你!
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 前置条件!(超级重要!说三遍!) :
- 必须调用
setMouseTracking(true)! - 否则永不触发此信号!
- 这是新手最容易忽略的!
- 必须调用
- 触发频率(超级重要!) :
- 鼠标在单元格间移动时高频触发;
- 避免在信号槽内执行耗时操作!
- 仅进不出(超级重要!) :
- 此信号仅响应 "鼠标进入" 单元格;
- 鼠标离开单元格需结合
QMouseEvent手动处理(没有cellLeft信号);
- 参数有效性 :
row/column始终为有效范围,无需额外校验。
4.3.2 使用示例
#include <QTableWidgetItem>
#include <QGuiApplication> // Qt::lightGray
// 【必须!】第一步:开启表格的鼠标跟踪!
ui->tableWidget->setMouseTracking(true);
// 第二步:绑定信号(用 Lambda 表达式)
connect(ui->tableWidget, &QTableWidget::cellEntered,
this, [=](int row, int col){
// 获取该单元格
QTableWidgetItem* item = ui->tableWidget->item(row, col);
if (item == nullptr) {
item = new QTableWidgetItem();
ui->tableWidget->setItem(row, col, item);
}
// 鼠标进入时设置浅灰背景
item->setBackground(Qt::lightGray);
// 注意:鼠标离开时恢复背景需结合鼠标事件手动处理
});
4.4 信号四:currentCellChanged (int row, int column, int previousRow, int previousColumn)------ 选中不同单元格时触发
4.4.1 信号的核心定义
currentCellChanged 是 QTableWidget 最核心、最常用 的选中变更信号 ------ 它在选中不同单元格时触发(选中同一条目不触发),同时返回 "当前选中单元格" 和 "上一个选中单元格" 的行 / 列号。
通俗理解:currentCellChanged 就像 "表格上标亮的格子变了时通知你"------ 它会告诉你 "之前标亮的是第几行第几列,现在标亮的是第几行第几列";如果你重复点击同一个格子,它不会通知你,因为标亮的格子没变。
这里有几个超级重要的规则,必须牢记:
- 判空处理(超级重要!) :
- 当前 / 上一个选中项不存在时,对应行 / 列号为 -1;
- 需先校验再操作!
- 触发规则(超级重要!) :
- 仅选中不同单元格时触发;
- 重复选中同一条目不触发;
- 代码触发(超级重要!) :
- 调用
setCurrentCell()/setCurrentItem()等代码选中单元格也会触发此信号;
- 调用
- 取消选中 :删除选中单元格时,
row/column为 -1,previousRow/previousColumn为原选中单元格位置。
4.4.2 信号参数详解
信号原型:
void QTableWidget::currentCellChanged(int row, int column, int previousRow, int previousColumn);
参数说明:
row:int类型,当前选中单元格的行号(无选中时为 -1);column:int类型,当前选中单元格的列号(无选中时为 -1);previousRow:int类型,上一个选中单元格的行号(无之前选中项时为 -1);previousColumn:int类型,上一个选中单元格的列号(无之前选中项时为 -1)。
4.4.3 使用示例
#include <QDebug>
// 绑定信号(用 Lambda 表达式)
connect(ui->tableWidget, &QTableWidget::currentCellChanged,
this, [=](int curRow, int curCol, int prevRow, int prevCol){
// 处理上一个选中位置
QString prevPos;
if (prevRow == -1 || prevCol == -1) {
prevPos = "无";
} else {
prevPos = QString("第%1行第%2列").arg(prevRow+1).arg(prevCol+1);
}
// 处理当前选中位置
QString curPos;
if (curRow == -1 || curCol == -1) {
curPos = "无";
} else {
curPos = QString("第%1行第%2列").arg(curRow+1).arg(curCol+1);
}
// 打印变更记录
qDebug() << "选中单元格变更:" << prevPos << " → " << curPos;
});
示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//OK,本文件我们来学习QTableWidget的核心信号,其实这个就真的是很简单·~~·
/**
* @class QTableWidget
* @brief Qt中表格控件的核心单元格交互信号(注:以下信号归属QTableWidget,非QTableWidgetItem)
* @details 这些信号覆盖QTableWidget最核心的单元格交互场景(点击、双击、鼠标悬浮、选中变更),是表格与业务逻辑联动的核心接口;
* 所有信号均返回单元格的行/列号(从0开始),可精准定位交互目标,适配各类表格操作场景。
*
* 【核心特征】
* 1. 点击交互:支持单击/双击单元格触发信号,直接返回目标单元格的行/列号;
* 2. 悬浮交互:支持鼠标进入单元格触发信号(需开启鼠标跟踪);
* 3. 选中变更:支持选中单元格切换时触发信号,同时返回当前/之前选中单元格的位置。
*/
// ============================== 核心信号详解 ==============================
/**
* @signal void QTableWidget::cellClicked(int row, int column)
* @brief **用户鼠标单击**表格单元格时触发的信号
* @details 纯交互触发信号,仅响应用户单击单元格操作,参数返回被点击单元格的行/列号;
* 点击表格空白区域(无单元格处)不会触发此信号。
*
* @参数说明:
* @param row - int类型,被点击单元格的行号(从0开始计数);
* @param column - int类型,被点击单元格的列号(从0开始计数)。
*
* @使用示例:
* // 绑定信号,单击单元格时打印位置并修改文本
* connect(ui->tableWidget, &QTableWidget::cellClicked, this, [=](int row, int col){
* qDebug() << "单击单元格:第" << row+1 << "行,第" << col+1 << "列";
* QTableWidgetItem* item = ui->tableWidget->item(row, col);
* if (item) {
* item->setText("已单击");
* }
* });
*
* 【关键注意事项】
* 1. 触发条件:仅用户**单击**单元格触发,代码选中单元格(setCurrentCell)不触发;
* 2. 参数有效性:row/column始终为有效范围(0 ≤ row < rowCount(),0 ≤ column < columnCount());
* 3. 选中联动:单击单元格会自动将其设为当前选中单元格,因此会先触发cellClicked(),再触发currentCellChanged();
* 4. 空白区:点击表格空白处(无单元格区域)不触发此信号。
*/
/**
* @signal void QTableWidget::cellDoubleClicked(int row, int column)
* @brief **用户鼠标双击**表格单元格时触发的信号
* @details 适配"双击单元格执行核心操作"的场景(如编辑单元格、打开详情),参数返回被双击单元格的行/列号。
*
* @参数说明:
* @param row - int类型,被双击单元格的行号(从0开始计数);
* @param column - int类型,被双击单元格的列号(从0开始计数)。
*
* @使用示例:
* // 绑定信号,双击单元格时编辑文本
* connect(ui->tableWidget, &QTableWidget::cellDoubleClicked, this, [=](int row, int col){
* QTableWidgetItem* item = ui->tableWidget->item(row, col);
* if (!item) {
* // 无单元格时创建新单元格
* item = new QTableWidgetItem();
* ui->tableWidget->setItem(row, col, item);
* }
* QString newText = QInputDialog::getText(this, "编辑单元格", "修改内容:",
* QLineEdit::Normal, item->text());
* if (!newText.isEmpty()) {
* item->setText(newText);
* }
* });
*
* 【关键注意事项】
* 1. 触发顺序:双击会先触发cellClicked()(第一次单击),再触发此信号;
* 2. 触发条件:仅用户**双击**触发,代码操作/单击均不触发;
* 3. 参数有效性:row/column始终为有效范围,无需额外校验;
* 4. 交互场景:适合"编辑、查看详情、打开关联数据"等需要双击确认的操作。
*/
/**
* @signal void QTableWidget::cellEntered(int row, int column)
* @brief **鼠标光标进入**表格单元格区域时触发的信号(需开启鼠标跟踪)
* @details 悬浮交互信号,用于实现"鼠标悬浮高亮单元格、显示提示信息"等效果;
* 默认关闭鼠标跟踪,需手动调用setMouseTracking(true)才会触发。
*
* @参数说明:
* @param row - int类型,鼠标进入的单元格行号(从0开始计数);
* @param column - int类型,鼠标进入的单元格列号(从0开始计数)。
*
* @使用示例:
* // 第一步:开启表格的鼠标跟踪
* ui->tableWidget->setMouseTracking(true);
* // 第二步:绑定信号,悬浮时高亮单元格背景
* connect(ui->tableWidget, &QTableWidget::cellEntered, this, [=](int row, int col){
* QTableWidgetItem* item = ui->tableWidget->item(row, col);
* if (!item) {
* item = new QTableWidgetItem();
* ui->tableWidget->setItem(row, col, item);
* }
* item->setBackground(Qt::lightGray); // 悬浮时设浅灰背景
* // 鼠标离开时恢复背景需结合鼠标事件实现
* });
*
* 【关键注意事项】
* 1. 前置条件:必须调用setMouseTracking(true),否则永不触发此信号;
* 2. 触发频率:鼠标在单元格间移动时高频触发,避免在信号槽内执行耗时操作;
* 3. 仅进不出:此信号仅响应"鼠标进入",鼠标离开单元格需结合QMouseEvent手动处理;
* 4. 参数有效性:row/column始终为有效范围,无需额外校验。
*/
/**
* @signal void QTableWidget::currentCellChanged(int row, int column, int previousRow, int previousColumn)
* @brief 选中**不同**单元格时触发的信号(选中同一条目不触发)
* @details 核心选中变更信号,同时返回"当前选中单元格"和"上一个选中单元格"的行/列号;
* 触发场景包括用户点击不同单元格、代码设置选中单元格、删除选中单元格等。
*
* @参数说明:
* @param row - int类型,当前选中单元格的行号(无选中时为-1);
* @param column - int类型,当前选中单元格的列号(无选中时为-1);
* @param previousRow - int类型,上一个选中单元格的行号(无之前选中项时为-1);
* @param previousColumn - int类型,上一个选中单元格的列号(无之前选中项时为-1)。
*
* @使用示例:
* // 绑定信号,打印选中单元格的变更记录
* connect(ui->tableWidget, &QTableWidget::currentCellChanged, this,
* [=](int curRow, int curCol, int prevRow, int prevCol){
* QString prevPos = (prevRow == -1) ? "无" : QString("第%1行第%2列").arg(prevRow+1).arg(prevCol+1);
* QString curPos = (curRow == -1) ? "无" : QString("第%1行第%2列").arg(curRow+1).arg(curCol+1);
* qDebug() << "选中单元格变更:" << prevPos << " → " << curPos;
* });
*
* 【关键注意事项】
* 1. 判空处理:当前/上一个选中项不存在时,对应行/列号为-1,需先校验再操作;
* 2. 触发规则:仅选中**不同**单元格时触发(重复选中同一条目不触发);
* 3. 代码触发:调用setCurrentCell()/setCurrentItem()等代码选中单元格也会触发此信号;
* 4. 取消选中:删除选中单元格时,row/column为-1,prevRow/prevCol为原选中单元格位置。
*/
//我们使用ui界面~
// 【必须】设置表格的行列数量
//要严格注意,在插入条目之前,必须先指明表格的行列数量才行哦~~~
ui->tw->setRowCount(2); // 2行
ui->tw->setColumnCount(2); // 2列
//然后还有就是,一般在我们设置完表格的行列数量之后
//qt就会自动在表格的上方和左方加上表头,1、2什么的
//要是我们想自定义,那么就得使用上面提到的
//setHorizonalHeaderItem方法和setVerticalHeaderItem方法
//指明是横还是竖的哪一行哪一列,然后进行设置
//注意:从0开始计数
// ================= 设置水平表头 (列标题) =================
// 注意:第二个参数必须是 QTableWidgetItem* 对象
// 第 0 列 表头
QTableWidgetItem* headerItem0 = new QTableWidgetItem("姓名");
// 可选:设置表头文字居中
headerItem0->setTextAlignment(Qt::AlignCenter);
ui->tw->setHorizontalHeaderItem(0, headerItem0);
// 第 1 列 表头
QTableWidgetItem* headerItem1 = new QTableWidgetItem("年龄");
headerItem1->setTextAlignment(Qt::AlignCenter);
ui->tw->setHorizontalHeaderItem(1, headerItem1);
// ================= 设置垂直表头 (行标题) =================
// 如果你想自定义左侧的行号 (默认是 1, 2, 3...)
// 第 0 行 表头
QTableWidgetItem* vHeaderItem0 = new QTableWidgetItem("第一行");
ui->tw->setVerticalHeaderItem(0, vHeaderItem0);
// 第 1 行 表头
QTableWidgetItem* vHeaderItem1 = new QTableWidgetItem("第二行");
ui->tw->setVerticalHeaderItem(1, vHeaderItem1);
// ================= 填充表格内容 =================
QTableWidgetItem* item1 = new QTableWidgetItem("张三");
QTableWidgetItem* item2 = new QTableWidgetItem("18");
QTableWidgetItem* item3 = new QTableWidgetItem("李四");
QTableWidgetItem* item4 = new QTableWidgetItem("20");
// 放入表格,要指定行和列哦~~~
ui->tw->setItem(0, 0, item1);
ui->tw->setItem(0, 1, item2);
ui->tw->setItem(1, 0, item3);
ui->tw->setItem(1, 1, item4);
ui->tw->setMouseTracking(true);//开启鼠标追踪
}
Widget::~Widget()
{
delete ui;
}
// 1. 单元格被单击
void Widget::on_tw_itemClicked(QTableWidgetItem *item)
{
// 触发时机:鼠标左键单击某个单元格时触发。
// 注意:如果点击的是已经选中的单元格,currentItemChanged 不会触发,但这个信号会触发。
if (!item) return; // 安全判断
int row = item->row();
int col = item->column();
QString text = item->text();
qDebug() << "[Table Clicked] 点击了单元格 -> 行:" << row << ", 列:" << col << ", 内容:" << text;
// 典型用法:
// 1. 记录当前点击位置,用于后续操作(如右键菜单)。
// 2. 在状态栏显示当前单元格的详细信息。
// ui->statusBar->showMessage(QString("当前位置: %1 行, %2 列").arg(row).arg(col));
}
// 2. 单元格被双击
void Widget::on_tw_itemDoubleClicked(QTableWidgetItem *item)
{
// 触发时机:快速双击某个单元格时触发。
if (!item) return;
int row = item->row();
int col = item->column();
qDebug() << "[Table Double Clicked] 双击了单元格 -> 行:" << row << ", 列:" << col;
// 典型用法:
// 1. 进入"编辑模式"(如果默认不可编辑)。
// 2. 打开详情对话框,加载该行数据。
// 3. 如果该单元格是文件路径,直接打开文件。
// 示例:强制开启编辑
// ui->tw->editItem(item);
}
// 3. 鼠标移入单元格
void Widget::on_tw_itemEntered(QTableWidgetItem *item)
{
// 触发时机:鼠标光标移入某个单元格区域时触发。
// 前提:确保 tableWidget 的 viewport 开启了鼠标追踪 (通常默认开启,若无效可手动设置)。
// ui->tw->viewport()->setMouseTracking(true);
if (!item) return;
QString tipContent = QString("第 %1 行,第 %2 列\n内容:%3")
.arg(item->row())
.arg(item->column())
.arg(item->text());
// 典型用法:
// 1. 显示 Tooltip,特别是当文字被截断时显示完整内容。
// 2. 动态高亮当前行或当前列(通过 QSS 或背景色)。
item->setToolTip(tipContent);
// 示例:高亮当前行背景 (临时效果)
// QColor oldColor = item->background().color();
// item->setBackground(QColor("#E0F7FA"));
// (注意:需要在离开时恢复颜色,通常配合 item 的其他逻辑或使用 StyleSheet)
}
// 4. 当前选中单元格改变
void Widget::on_tw_currentItemChanged(QTableWidgetItem *current, QTableWidgetItem *previous)
{
// 触发时机:当"当前活动单元格"(有焦点框的那个)发生变化时触发。
// 参数说明:
// current: 新选中的单元格指针 (若取消选中则为 nullptr)
// previous: 原来选中的单元格指针
qDebug() << "[Current Item Changed]";
if (current) {
int r = current->row();
int c = current->column();
qDebug() << "新选中 -> 行:" << r << ", 列:" << c << ", 文本:" << current->text();
// 典型用法:
// 1. 联动更新其他控件(例如:选中表格某行,右侧表单显示该行详情)。
// 2. 根据列的不同执行不同逻辑(例如:只有点击"价格"列才显示货币转换器)。
// 示例:根据列号判断逻辑
/*
if (c == 2) { // 假设第3列是操作列
ui->btnEdit->setEnabled(true);
} else {
ui->btnEdit->setEnabled(false);
}
*/
} else {
qDebug() << "已取消所有选中";
// 清空关联的详情显示
// ui->lineEditDetail->clear();
}
}
第五章 综合示例:学生信息管理表格
讲完了所有内容,我们最后来做一个综合示例,结合你提供的资料,实现一个完整的 "学生信息管理表格"------ 这是 QTableWidget 最经典的应用场景之一。
5.1 场景描述
界面上有:
- 一个 QTableWidget(
objectName为tableWidget); - 四个 QPushButton:
pushButton_addRow:添加新行;pushButton_delRow:删除选中行;pushButton_addCol:添加新列(需配合 QLineEdit 输入列名);pushButton_delCol:删除选中列;
- 一个 QLineEdit(
objectName为lineEdit_colName):用于输入新列的列名。
功能:
- 初始化表格:3 行 3 列,列标题为 "学号""姓名""年龄",填充初始数据;
- 点击 "添加新行":在表格末尾插入一行空行;
- 点击 "删除选中行":删除当前选中的行;
- 点击 "添加新列":在表格末尾插入一列,列标题为 LineEdit 中的内容;
- 点击 "删除选中列":删除当前选中的列;
- 绑定交互信号:点击、双击、悬浮、选中变更时打印日志。
5.2 代码实现
#include "widget.h"
#include "ui_widget.h"
#include <QTableWidgetItem>
#include <QFont>
#include <QDebug>
#include <QInputDialog>
#include <QLineEdit>
#include <QGuiApplication>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// ================= 1. 初始化表格结构 =================
// 【必须!】设置行列数
ui->tableWidget->setRowCount(3); // 3 行
ui->tableWidget->setColumnCount(3); // 3 列
// ================= 2. 设置水平表头(列标题) =================
QStringList headers = {"学号", "姓名", "年龄"};
for (int c = 0; c < headers.size(); ++c) {
QTableWidgetItem* headerItem = new QTableWidgetItem(headers[c]);
headerItem->setFont(QFont("微软雅黑", 12, QFont::Bold)); // 表头加粗
headerItem->setTextAlignment(Qt::AlignCenter); // 表头居中
ui->tableWidget->setHorizontalHeaderItem(c, headerItem);
}
// ================= 3. 填充初始数据 =================
// 第 1 行(索引 0)
ui->tableWidget->setItem(0, 0, new QTableWidgetItem("1001"));
ui->tableWidget->setItem(0, 1, new QTableWidgetItem("张三"));
ui->tableWidget->setItem(0, 2, new QTableWidgetItem("20"));
// 第 2 行(索引 1)
ui->tableWidget->setItem(1, 0, new QTableWidgetItem("1002"));
ui->tableWidget->setItem(1, 1, new QTableWidgetItem("李四"));
ui->tableWidget->setItem(1, 2, new QTableWidgetItem("21"));
// 第 3 行(索引 2)
ui->tableWidget->setItem(2, 0, new QTableWidgetItem("1003"));
ui->tableWidget->setItem(2, 1, new QTableWidgetItem("王五"));
ui->tableWidget->setItem(2, 2, new QTableWidgetItem("19"));
// ================= 4. 开启鼠标跟踪(用于 cellEntered 信号) =================
ui->tableWidget->setMouseTracking(true);
// ================= 5. 绑定交互信号 =================
// 信号 1:cellClicked(单击单元格)
connect(ui->tableWidget, &QTableWidget::cellClicked,
this, [=](int row, int col){
qDebug() << "[单击] 第" << row+1 << "行,第" << col+1 << "列";
});
// 信号 2:cellDoubleClicked(双击单元格)
connect(ui->tableWidget, &QTableWidget::cellDoubleClicked,
this, [=](int row, int col){
qDebug() << "[双击] 第" << row+1 << "行,第" << col+1 << "列";
// 双击编辑
QTableWidgetItem* item = ui->tableWidget->item(row, col);
if (item == nullptr) {
item = new QTableWidgetItem();
ui->tableWidget->setItem(row, col, item);
}
QString newText = QInputDialog::getText(this, "编辑", "修改内容:",
QLineEdit::Normal, item->text());
if (!newText.isEmpty()) {
item->setText(newText);
}
});
// 信号 3:cellEntered(鼠标进入单元格)
connect(ui->tableWidget, &QTableWidget::cellEntered,
this, [=](int row, int col){
Q_UNUSED(row);
Q_UNUSED(col);
// 这里可以做悬浮高亮,为了简单我们就不实现恢复背景了
// qDebug() << "[悬浮] 第" << row+1 << "行,第" << col+1 << "列";
});
// 信号 4:currentCellChanged(选中变更)
connect(ui->tableWidget, &QTableWidget::currentCellChanged,
this, [=](int curRow, int curCol, int prevRow, int prevCol){
Q_UNUSED(prevRow);
Q_UNUSED(prevCol);
if (curRow != -1 && curCol != -1) {
qDebug() << "[选中变更] 当前:第" << curRow+1 << "行,第" << curCol+1 << "列";
} else {
qDebug() << "[选中变更] 无选中";
}
});
}
Widget::~Widget()
{
delete ui;
}
// ================= 按钮槽函数 =================
// 1. 添加新行
void Widget::on_pushButton_addRow_clicked()
{
int rowCount = ui->tableWidget->rowCount();
ui->tableWidget->insertRow(rowCount); // 在末尾插入
qDebug() << "[操作] 添加新行,当前总行数:" << ui->tableWidget->rowCount();
}
// 2. 删除选中行
void Widget::on_pushButton_delRow_clicked()
{
int curRow = ui->tableWidget->currentRow();
if (curRow != -1) {
ui->tableWidget->removeRow(curRow);
qDebug() << "[操作] 删除第" << curRow+1 << "行,当前总行数:" << ui->tableWidget->rowCount();
} else {
qDebug() << "[操作] 未选中行,无法删除";
}
}
// 3. 添加新列
void Widget::on_pushButton_addCol_clicked()
{
const QString& colName = ui->lineEdit_colName->text();
if (colName.isEmpty()) {
qDebug() << "[操作] 列名为空,无法添加";
return;
}
int colCount = ui->tableWidget->columnCount();
ui->tableWidget->insertColumn(colCount); // 在末尾插入
// 设置新列的表头
QTableWidgetItem* headerItem = new QTableWidgetItem(colName);
headerItem->setFont(QFont("微软雅黑", 12, QFont::Bold));
headerItem->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setHorizontalHeaderItem(colCount, headerItem);
// 清空 LineEdit
ui->lineEdit_colName->clear();
qDebug() << "[操作] 添加新列:" << colName << ",当前总列数:" << ui->tableWidget->columnCount();
}
// 4. 删除选中列
void Widget::on_pushButton_delCol_clicked()
{
int curCol = ui->tableWidget->currentColumn();
if (curCol != -1) {
ui->tableWidget->removeColumn(curCol);
qDebug() << "[操作] 删除第" << curCol+1 << "列,当前总列数:" << ui->tableWidget->columnCount();
} else {
qDebug() << "[操作] 未选中列,无法删除";
}
}
第六章 全文总结与学习建议
恭喜你!终于看完了这篇 QTableWidget 与 QTableWidgetItem 详细解析!
如果你跟着文章一步步敲了代码,做了练习,那么现在你已经完全掌握了它们的核心内容:
- 你知道了 QTableWidget 是二维表格控件,QTableWidgetItem 是表格中的单个单元格;
- 你会用 QTableWidgetItem 的
row、column、setText、setTextAlignment、setIcon、setSelected、setSizeHint、setFont定制单元格; - 你会用 QTableWidget 的
item、setItem、currentItem、currentRow、currentColumn、rowCount、columnCount、insertRow、insertColumn、removeRow、removeColumn、setHorizontalHeaderItem、setVerticalHeaderItem操作表格; - 你会绑定
cellClicked、cellDoubleClicked、cellEntered、currentCellChanged等信号实现交互; - 你知道了在插入条目之前必须先设置行列数! 行列从 0 开始! removeRow/removeColumn 会自动释放单元格! cellEntered 必须先开启鼠标跟踪! 这些超级重要的注意事项。
毫不夸张地说,掌握了这些内容,你就掌握了 QTableWidget 开发的 95% 以上的需求!
6.1 核心要点回顾(最后再记一遍!)
在结束之前,我们最后再回顾一下这篇文章的核心要点,特别是那些最容易踩坑的地方:
- 在插入条目之前必须先设置行列数!(超级重要!开篇就讲!);
- 行列从 0 开始!(超级重要!说三遍!):用户视角需 +1;
- item ()、currentItem () 必须先判空!(超级重要!):否则程序崩溃!
- removeRow/removeColumn 会自动释放单元格!(超级重要!):无需手动 delete!
- setItem () 设置新单元格前,原单元格需手动 delete!(超级重要!);
- cellEntered 必须先调用 setMouseTracking (true)!(超级重要!);
- 图标显示尺寸由 QTableWidget::setIconSize () 全局控制!(超级重要!);
- QFont 不包含颜色,文本颜色需通过 setForeground () 设置!(超级重要!);
- cellClicked 仅用户单击触发,代码选中不触发!(超级重要!);
- 重复点击同一单元格,cellClicked 触发,currentCellChanged 不触发!(超级重要!)。
6.2 最后的话
编程学习没有捷径,唯手熟尔。QTableWidget 和 QTableWidgetItem 的内容虽然不少,但只要你多敲代码、多做练习、多踩坑、多排查,很快就能熟练掌握。
这篇文章虽然很长,但我相信,如果你认真看完了,跟着敲了代码,你一定会对它们有一个极其深刻的理解,再也不会为表格开发发愁。
感谢你阅读这篇文章,希望它能帮到你。我们下一篇 Qt 教程再见