开篇介绍:
hello 大家,本篇博客我们来学习QListWidget常见属性以及QListWidgetItem类。
在 Qt 桌面应用开发中,我们除了会遇到 "单元素输入"(如 QLineEdit、QSlider、QDial)的需求,还会经常遇到一个更通用、更常见、更核心的需求:展示和管理一个纵向的列表------ 比如展示文件列表、展示联系人列表、展示播放列表、展示设置选项列表、展示搜索结果列表。在这些场景下,你需要一个控件能把多个条目纵向排列,支持用户选中、点击、双击、新增、删除条目 ------ 这正是 QListWidget 的用武之地。
为了满足这个需求,Qt 专门为我们提供了一个开箱即用、功能强大、使用最广泛的列表控件:QListWidget(列表控件)。QListWidget 就像 "一个纵向排列的清单"------ 它能显示多个条目,每个条目可以是纯文本,也可以是 "图标 + 文本";它支持用户选中条目、点击条目、双击条目;它支持在末尾添加条目、在任意位置插入条目、删除指定位置的条目;它支持自动排序、条目换行、自定义条目间距和对齐方式。
而 QListWidget 中的每一个条目,都是由 QListWidgetItem(列表项类) 来表示的 ------QListWidgetItem 是 QListWidget 的最小组成单元,核心由 "文本 + 图标" 构成,你可以单独设置每个条目的字体、图标、显示状态、尺寸、选中状态、文本对齐方式。
很多新手刚接触 QListWidget 和 QListWidgetItem 时,会觉得它们很简单 ------ 不就是一个列表吗?拖上去,addItem 几个字符串,连接信号,就完事了。但用起来才发现,这里面有很多实用的细节和坑:比如 QListWidgetItem 必须用 new 创建,不能是栈上的对象,否则界面上看不到条目;比如 takeItem 只是把条目从列表里移除,不会自动释放内存,必须手动 delete;比如 currentItem 可能返回 nullptr,必须先判空再操作,否则程序会崩溃;比如行号是从 0 开始计数的,不是从 1 开始;比如开启 sortingEnabled 后,新增条目会自动排序,原有的行号会失效。
别担心!这篇文章我会先讲 QListWidgetItem 类的核心方法 (setText、setFont、setIcon、setHidden、setSizeHint、setSelected、setTextAlignment),再讲 QListWidget 的核心属性 (currentRow、count、itemAlignment、selectRectVisible、spacing、sortingEnabled、isWrapping),接着讲 QListWidget 的核心方法 (addItem、currentItem、setCurrentItem、setCurrentRow、insertItem、item、takeItem),最后讲 QListWidget 的核心交互信号 (currentItemChanged、currentRowChanged、itemClicked、itemDoubleClicked、itemEntered、itemPressed、itemSelectionChanged、currentTextChanged)。
话不多说,我们正式开始!
第一章 先搞懂基础:QListWidget 和 QListWidgetItem 是什么?
在讲具体内容之前,我们必须先搞懂两个最基础、最重要的问题:QListWidget 是用来做什么的?QListWidgetItem 是用来做什么的?以及,它们和 QListView 的关系是什么?
1.1 QListWidget 的核心定位
QListWidget 是 Qt Widgets 模块中用于纵向展示和管理多个条目的核心通用控件 ------ 它继承自 QListView(列表视图),但比 QListView 更简单、更易用,因为它内置了 "条目管理" 的功能,不需要你手动实现数据模型(Model)和视图(View)的分离。
通俗理解:QListWidget 就像 "我们平时写的购物清单""手机上的联系人列表""音乐播放器的播放列表"------ 它是一个纵向排列的列表,每个条目占一行;你可以在清单里添加新的一行,也可以删掉某一行;你可以点击某一行选中它,也可以双击某一行执行操作;它支持自动排序,也支持条目多列显示。
QListWidget 内置了非常多的功能,不需要你手动实现:
- 它支持在列表末尾 添加条目(
addItem),也支持在任意位置 插入条目(insertItem); - 它支持删除指定位置 的条目(
takeItem); - 它支持获取当前选中 的条目(
currentItem)或选中的行号 (currentRow); - 它支持通过行号 获取对应的条目(
item); - 它支持统计列表中总共有多少行 (
count); - 它支持设置条目之间的间距 (
spacing)、条目的整体对齐方式 (itemAlignment); - 它支持自动排序 (
sortingEnabled)、条目换行 (isWrapping); - 它支持丰富的交互信号:选中变更、点击、双击、鼠标悬浮等;
- 它的样式可以通过 QSS(Qt 样式表)完全自定义。
总之,QListWidget 是桌面端 "纵向展示和管理多个条目" 场景的通用首选组件------ 只要是想展示一个列表,用 QListWidget 就对了。
1.2 QListWidgetItem 的核心定位
QListWidgetItem 是 Qt 中表示 QListWidget 中单个条目的核心类------ 它是 QListWidget 的最小组成单元,每个 QListWidgetItem 对应列表中的一行。
通俗理解:QListWidgetItem 就像 "购物清单里的每一行纸"------ 这张纸上可以写文字(setText),可以贴图标(setIcon),可以设置字体(setFont),可以设置对齐方式(setTextAlignment);你可以把这张纸藏起来(setHidden),也可以把它标记为 "已选中"(setSelected);你还可以设置这张纸的大小(setSizeHint)。
QListWidgetItem 的核心特征非常简单:
- 它本质上是一个 "文本 + 图标" 的组合体 ------ 这是它最核心的视觉内容;
- 每个条目可以独立设置样式和状态------ 你可以让第一个条目是红色字体,第二个条目是蓝色字体,第三个条目带图标,第四个条目隐藏;
- 它的内存由 QListWidget 管理(通过
addItem添加后)------ 但通过takeItem移除后,需要你手动释放。
1.3 QListWidget 和 QListView 的关系(必知!)
- QListWidget 是 QListView 的子类 ------ 它在 QListView 的基础上,内置了一个简单的数据模型(
QStandardItemModel),让你可以直接操作条目,而不需要手动实现 Model/View 架构; - QListWidget 比 QListView 更简单、更易用------ 如果你只是想展示一个简单的列表,不需要复杂的数据模型,用 QListWidget 就够了;如果你需要展示大量数据(比如成千上万条),或者需要自定义数据模型,再考虑用 QListView + 自定义 Model。
1.4 一个超级重要的注意事项
在正式开始之前,有一个超级重要、新手最容易踩坑、一踩就崩溃的注意事项,必须开篇就讲,刻在脑子里:
严格注意!我们创建的 QListWidgetItem 对象,不能是栈上的对象,必须要用
new出来的 QListWidgetItem!否则代码结束后,这些局部对象会被自动销毁,QListWidget 里保存的指针就变成了无效地址,所以界面上看不到这些条目!
通俗理解:你不能把一张 "临时的纸"(栈对象)交给清单保管,因为清单还没保存好,这张纸就被你扔了(自动销毁);你必须把一张 "动态分配的纸"(new 出来的堆对象)交给清单,清单会一直保管它,直到你把它抽走(takeItem)。
错误示例(栈对象,界面上看不到!):
// 错误!栈上创建的 item,函数结束后自动销毁
QListWidgetItem item("错误示例");
ui->listWidget->addItem(&item); // 界面上看不到!
正确示例(堆对象,界面上正常显示!):
// 正确!new 出来的 item,交给 QListWidget 管理
QListWidgetItem* item = new QListWidgetItem("正确示例");
ui->listWidget->addItem(item); // 界面上正常显示!
这个注意事项超级重要,后面讲 addItem 和 insertItem 时我还会再强调,但现在必须先记住!
第二章 QListWidgetItem 类核心方法详解
好,我们正式开始!按照你提供的顺序,我们首先讲 QListWidgetItem 类的核心方法------ 因为要往 QListWidget 里添加条目,首先得搞懂条目本身怎么设置。QListWidgetItem 的方法不多,但都很实用,核心围绕 "文本、图标、字体、状态、尺寸、对齐" 展开。
2.1 方法一:setText () & text ()------ 设置 / 获取条目文本
2.1.1 方法的核心定义
setText() 是 QListWidgetItem 最基础、最常用、最高频 的方法 ------ 它用于设置列表项的核心显示文本;text() 是对应的获取方法,用于获取当前条目显示的文本。
通俗理解:setText() 就像 "在清单的这一行纸上写字"------ 你想让这一行显示什么,就写什么;text() 就像 "读这一行纸上写的是什么字"。
这里有几个超级重要的规则,必须牢记:
- 文本是条目的核心标识------ 未设置时条目为空,显示为空白行;
- 支持普通字符串和富文本(HTML 格式) ------ 你可以写普通的文字,也可以写简单的 HTML 标签(如
<b>加粗、<i>斜体、<font>改颜色); - 支持 UTF-8 编码------ 可以包含中文、特殊字符,不会乱码(只要你的源文件编码是 UTF-8,Qt 默认支持);
- 文本过长时会自动截断 ------ 如果文本太长,列表项会自动截断并显示省略号(
...),你可以通过setSizeHint()扩大条目尺寸来避免。
2.1.2 关联 API 详解(逐词逐句,零模糊)
setText() 和 text() 是一对配套的方法,我们逐个来讲:
1. 设置条目显示文本:void setText (const QString &text)
函数原型:
void QListWidgetItem::setText(const QString &text);
逐词逐句底层解析:
void:函数没有返回值,只是执行 "设置文本" 的操作;QListWidgetItem:::说明这个函数是QListWidgetItem类的成员函数,只能用 QListWidgetItem 对象调用;setText():函数名,很直观,就是 "设置文本" 的意思;const QString &text:入参,text是你要显示的文本内容,QString是 Qt 中的字符串类,const &是常量引用,避免拷贝。
参数说明:
text:要显示的文本内容,QString类型;- 支持普通字符串,也支持简单的 HTML 富文本标签;
- 可以是空字符串(显示为空白行)。
2. 获取条目显示文本:QString text () const
函数原型:
QString QListWidgetItem::text() const;
逐词逐句底层解析:
QString:返回值类型,返回当前条目显示的文本;QListWidgetItem:::成员函数;text():函数名,"获取文本" 的意思;const:常成员函数,不会修改条目状态。
返回值说明:
- 返回
QString类型的字符串; - 就是你之前通过
setText()设置的内容。
2.1.3 使用示例
#include <QListWidgetItem>
// 示例1:设置普通文本
QListWidgetItem* item1 = new QListWidgetItem();
item1->setText("普通文本条目");
ui->listWidget->addItem(item1);
// 示例2:设置富文本(带颜色、加粗)
QListWidgetItem* item2 = new QListWidgetItem();
item2->setText("<font color='red'><b>富文本条目(红色加粗)</b></font>");
ui->listWidget->addItem(item2);
// 示例3:获取条目的文本并打印
QString text = item1->text();
qDebug() << "条目1的文本:" << text; // 输出"普通文本条目"
2.1.4 关键注意事项(必知!)
- 富文本支持(超级重要!) :仅支持基础 HTML 标签(
<b>/<i>/<font>等),复杂标签(如<table>、<img>)可能无法渲染; - 文本截断(超级重要!) :文本过长时会自动截断并显示省略号,可通过
setSizeHint()扩大尺寸避免; - 编码适配(超级重要!):确保源文件编码为 UTF-8,避免中文乱码(Qt Creator 默认是 UTF-8,没问题);
- 空字符串:可以设置为空字符串,条目显示为空白行。
2.2 方法二:setFont () & font ()------ 设置 / 获取条目字体
2.2.1 方法的核心定义
setFont() 是 QListWidgetItem 用于自定义单个条目字体样式 的方法 ------ 你可以设置字体的家族(如微软雅黑、Arial)、大小(如 12 号、14 号)、粗细(如粗体、正常)、是否斜体、是否下划线等;font() 是对应的获取方法。
通俗理解:setFont() 就像 "给这一行纸上的字换字体"------ 你可以让这一行的字更大、更粗、换一种字体;font() 就像 "看看这一行用的是什么字体"。
这里有几个超级重要的规则,必须牢记:
- 优先级高于全局字体------ 单个条目的字体优先级高于 QListWidget 的全局字体,更高于应用程序的默认字体;
- 未单独设置时继承父控件字体------ 如果你没给这个条目单独设置字体,它会自动用 QListWidget 的字体;
- QFont 仅控制字体样式,不控制颜色 ------ 注意!字体颜色不是通过
QFont设置的,而是通过setForeground()设置的(比如item->setForeground(Qt::red)把文本设为红色); - 设置后立即生效 ------ 调用
setFont()后,列表项的视觉效果会立即刷新,无需额外刷新控件。
2.2.2 关联 API 详解(逐词逐句,零模糊)
1. 设置条目字体样式:void setFont (const QFont &font)
函数原型:
void QListWidgetItem::setFont(const QFont &font);
逐词逐句底层解析:
void:无返回值;QListWidgetItem:::成员函数;setFont():函数名,"设置字体" 的意思;const QFont &font:入参,font是QFont类型的对象,包含字体的所有样式信息。
参数说明:
font:QFont类型,包含字体家族、大小、粗细、斜体、下划线等样式;- 你可以通过
QFont的构造函数或setFamily()、setPointSize()、setBold()等方法来设置。
2. 获取条目字体样式:QFont font () const
函数原型:
QFont QListWidgetItem::font() const;
逐词逐句底层解析:
QFont:返回值类型,返回当前条目的字体样式;QListWidgetItem:::成员函数;font():函数名,"获取字体" 的意思;const:常成员函数。
返回值说明:
- 返回
QFont类型的对象; - 就是你之前通过
setFont()设置的内容,未设置则返回父控件的字体。
2.2.3 使用示例
#include <QListWidgetItem>
#include <QFont>
// 创建条目
QListWidgetItem* item = new QListWidgetItem("自定义字体条目");
// 创建 QFont 对象并设置样式
QFont font;
font.setFamily("微软雅黑"); // 字体家族:微软雅黑
font.setPointSize(14); // 字体大小:14 号
font.setBold(true); // 字体粗细:粗体
font.setItalic(true); // 是否斜体:是
// 给条目设置字体
item->setFont(font);
// 添加到列表
ui->listWidget->addItem(item);
// 获取并打印字体信息
QFont currentFont = item->font();
qDebug() << "字体家族:" << currentFont.family();
qDebug() << "字体大小:" << currentFont.pointSize();
2.2.4 关键注意事项(必知!)
- 优先级(超级重要!):单个条目字体 > QListWidget 全局字体 > 应用程序默认字体;
- 颜色设置(超级重要!) :QFont 仅控制字体样式,文本颜色需通过
setForeground()设置,不是setFont()! - 动态生效:设置后立即刷新视觉效果,无需额外操作;
- 未设置则继承:未单独设置字体时,继承 QListWidget 的全局字体。
2.3 方法三:setIcon () & icon ()------ 设置 / 获取条目图标
2.3.1 方法的核心定义
setIcon() 是 QListWidgetItem 用于为条目添加 / 修改显示图标 的方法 ------ 图标会显示在文本的左侧(默认布局),是实现 "图标 + 文本" 列表项的核心方法;icon() 是对应的获取方法。
通俗理解:setIcon() 就像 "在清单这一行纸的左边贴一张小图片"------ 比如文件列表里的文件夹图标、音乐列表里的音符图标;icon() 就像 "看看这一行贴的是什么图片"。
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 图标显示在文本左侧(默认布局)------ 这是 QListWidget 的默认布局,图标在左,文本在右;
- 未设置时仅显示文本------ 如果你没给条目设置图标,它就只显示文本,左边是空的;
- 图标显示尺寸由 QListWidget 全局控制!(超级重要!说三遍!) :
- 这点非常容易误解!单个条目无法单独设置图标的显示尺寸!
- 所有条目的图标显示尺寸由 QListWidget 的
setIconSize()方法全局统一控制; - 比如你调用
ui->listWidget->setIconSize(QSize(24, 24)),所有条目的图标都会显示为 24x24 像素;
- 支持多种图标来源 ------ 你可以用资源文件(
:/" 开头)、本地图片(完整路径)、系统图标(QStyle::standardIcon()`); - QIcon 自动适配不同显示状态 ------QIcon 会自动适配条目的 "选中 / 未选中" 状态,显示不同的图标(如果你通过
QIcon::addPixmap()自定义了状态图标);如果没自定义,就显示同一个图标。
2.3.2 关联 API 详解(逐词逐句,零模糊)
1. 设置条目显示图标:void setIcon (const QIcon &icon)
函数原型:
void QListWidgetItem::setIcon(const QIcon &icon);
逐词逐句底层解析:
void:无返回值;QListWidgetItem:::成员函数;setIcon():函数名,"设置图标" 的意思;const QIcon &icon:入参,icon是QIcon类型的对象。
参数说明:
icon:QIcon类型,支持资源文件、本地图片、系统图标等多种来源。
2. 获取条目显示图标:QIcon icon () const
函数原型:
QIcon QListWidgetItem::icon() const;
逐词逐句底层解析:
QIcon:返回值类型,返回当前条目的图标;QListWidgetItem:::成员函数;icon():函数名,"获取图标" 的意思;const:常成员函数。
返回值说明:
- 返回
QIcon类型的对象; - 未设置图标则返回空的 QIcon。
2.3.3 使用示例
#include <QListWidgetItem>
#include <QIcon>
#include <QApplication>
#include <QStyle>
// 先设置 QListWidget 的全局图标尺寸(超级重要!所有条目共用!)
ui->listWidget->setIconSize(QSize(32, 32)); // 图标显示为 32x32 像素
// 示例1:使用资源文件图标(路径以 :/ 开头,需先在 .qrc 文件中配置)
QListWidgetItem* item1 = new QListWidgetItem("资源图标条目");
item1->setIcon(QIcon(":/images/folder.png")); // 假设资源文件里有 folder.png
ui->listWidget->addItem(item1);
// 示例2:使用本地图片(传入完整路径)
QListWidgetItem* item2 = new QListWidgetItem("本地图片条目");
item2->setIcon(QIcon("C:/Users/Win/Desktop/icon.jpg")); // 本地图片完整路径
ui->listWidget->addItem(item2);
// 示例3:使用系统图标(通过 QStyle 获取,无需额外图片文件)
QListWidgetItem* item3 = new QListWidgetItem("系统图标条目");
// 获取系统标准文件图标
QIcon systemIcon = QApplication::style()->standardIcon(QStyle::SP_FileIcon);
item3->setIcon(systemIcon);
ui->listWidget->addItem(item3);
2.3.4 关键注意事项(必知!)
- 图标显示尺寸由 QListWidget 全局控制!(超级重要!说三遍!) :单个条目无法单独设置,必须用
ui->listWidget->setIconSize()全局设置! - 图标来源(超级重要!) :资源文件路径以
:/开头,本地图片需传入完整路径,系统图标通过QStyle::standardIcon()获取; - 默认布局:图标显示在文本左侧;
- QIcon 自动适配状态 :可通过
QIcon::addPixmap()自定义选中 / 未选中状态的不同图标。
2.4 方法四:setHidden () & isHidden ()------ 设置 / 获取条目是否隐藏
2.4.1 方法的核心定义
setHidden() 是 QListWidgetItem 用于控制单个条目显示 / 隐藏状态 的方法 ------ 隐藏的条目不会在列表中显示,也不参与列表布局计算;isHidden() 是对应的获取方法,用于判断条目是否处于隐藏状态。
通俗理解:setHidden(true) 就像 "把这一行纸从清单里藏起来"------ 别人看不到这一行,清单里的其他行会自动往上挪,填补这一行的位置;setHidden(false) 就像 "把这一行纸又放回清单里";isHidden() 就像 "看看这一行纸是不是藏起来了"。
这里有几个超级重要的规则,必须牢记:
- 隐藏的条目不占用布局空间 ------ 和
setDisabled()(禁用)不一样,禁用只是让条目变灰、不能点击,但它还在原来的位置,占用空间;隐藏是完全移除视觉展示,不占空间,其他条目会自动重新排列; - 仅影响显示,数据完全保留------ 隐藏只是让别人看不到,条目的文本、图标、选中状态等所有数据都完全保留,没有丢失;
- 交互屏蔽------ 隐藏的条目无法被选中、点击、双击,也不会响应任何交互事件;
- 区别于删除 ------ 隐藏不是删除!删除是把条目从列表里彻底移除(
takeItem),隐藏只是暂时藏起来,随时可以再显示。
2.4.2 关联 API 详解(逐词逐句,零模糊)
1. 设置条目是否隐藏:void setHidden (bool hidden)
函数原型:
void QListWidgetItem::setHidden(bool hidden);
逐词逐句底层解析:
void:无返回值;QListWidgetItem:::成员函数;setHidden():函数名,"设置是否隐藏" 的意思;bool hidden:入参,hidden是true隐藏,false显示(默认)。
参数说明:
hidden:true隐藏条目,false显示条目(默认状态是显示)。
2. 判断条目是否隐藏:bool isHidden () const
函数原型:
bool QListWidgetItem::isHidden() const;
逐词逐句底层解析:
bool:返回值类型,返回true或false;QListWidgetItem:::成员函数;isHidden():函数名,"是不是隐藏了" 的意思;const:常成员函数。
返回值说明:
true表示条目处于隐藏状态;false表示条目处于显示状态(默认)。
2.4.3 使用示例
#include <QListWidgetItem>
// 先添加几个条目
ui->listWidget->addItem("条目1");
ui->listWidget->addItem("条目2");
ui->listWidget->addItem("条目3");
// 获取第 0 个条目(第一行)
QListWidgetItem* item = ui->listWidget->item(0);
// 示例1:隐藏这个条目
item->setHidden(true);
// 此时界面上看不到"条目1","条目2"和"条目3"会自动往上挪
// 示例2:判断条目是否隐藏
if (item->isHidden()) {
qDebug() << "条目1 被隐藏了";
}
// 示例3:重新显示这个条目
item->setHidden(false);
// 此时"条目1"又会出现在第一行,其他条目自动往下挪
2.4.4 关键注意事项(必知!)
- 布局影响(超级重要!):隐藏的条目不占用布局空间,其他条目会自动重新排列;
- 与 setDisabled () 的区别(超级重要!) :
setHidden(true):隐藏,不占空间,不响应交互;setDisabled(true):禁用,仍占空间,显示为灰色,不响应交互;
- 数据保留(超级重要!):隐藏仅影响显示,所有数据完全保留;
- 区别于删除:隐藏不是删除,随时可以重新显示。
2.5 方法五:setSizeHint () & sizeHint ()------ 设置 / 获取条目尺寸提示
2.5.1 方法的核心定义
setSizeHint() 是 QListWidgetItem 用于为单个条目设置固定尺寸提示 的方法 ------ 你可以设置条目的宽度和高度(单位:像素),优先级高于 QListWidget 的默认条目尺寸;sizeHint() 是对应的获取方法。
通俗理解:setSizeHint() 就像 "给这一行纸设定固定的大小"------ 比如你想让这一行更宽、更高,就可以用这个方法;"尺寸提示" 的意思是,Qt 会尽量按照你设定的尺寸来显示,但如果内容太大,还是会自动适配。
这里有几个超级重要的规则,必须牢记:
- 优先级高于默认尺寸 ------ 如果你给条目设置了
sizeHint,Qt 会优先用你设定的尺寸;未设置时,条目尺寸由内容(文本 + 图标)和控件样式自动计算; - 宽度可能被拉伸 ------ 如果 QListWidget 的
resizeMode是AdjustToContents,或者 QListWidget 本身是固定宽度,条目的宽度可能被内容拉伸,需结合控件固定宽度使用; - 统一尺寸的影响 ------ 如果 QListWidget 设置了
setUniformItemSizes(true)(所有条目使用统一尺寸),那么只有第一个条目的sizeHint会生效,其他条目的单独设置无效; - 最小尺寸限制------ 如果你设置的尺寸小于内容的最小显示尺寸,Qt 会自动适配为内容的最小尺寸,不会让内容显示不全;
- 配合文本对齐效果更明显 ------ 如果你想让
setTextAlignment()(文本对齐)的效果更明显,通常需要先给条目设置一个较大的sizeHint,否则条目尺寸刚好包裹内容,对齐效果看不出来。
2.5.2 关联 API 详解(逐词逐句,零模糊)
1. 设置条目尺寸提示:void setSizeHint (const QSize &size)
函数原型:
void QListWidgetItem::setSizeHint(const QSize &size);
逐词逐句底层解析:
void:无返回值;QListWidgetItem:::成员函数;setSizeHint():函数名,"设置尺寸提示" 的意思;const QSize &size:入参,size是QSize类型,包含宽度和高度。
参数说明:
size:QSize类型,width为条目宽度,height为条目高度(单位:像素);- 比如
QSize(200, 50)表示宽 200 像素,高 50 像素。
2. 获取条目尺寸提示:QSize sizeHint () const
函数原型:
QSize QListWidgetItem::sizeHint() const;
逐词逐句底层解析:
QSize:返回值类型,返回当前条目的尺寸提示;QListWidgetItem:::成员函数;sizeHint():函数名,"获取尺寸提示" 的意思;const:常成员函数。
返回值说明:
- 返回
QSize类型的对象; - 未设置则返回 Qt 自动计算的尺寸。
2.5.3 使用示例
#include <QListWidgetItem>
#include <QSize>
// 创建条目
QListWidgetItem* item = new QListWidgetItem("自定义尺寸条目");
// 设置条目尺寸:宽 200 像素,高 50 像素
item->setSizeHint(QSize(200, 50));
// 添加到列表
ui->listWidget->addItem(item);
// 获取并打印尺寸
QSize size = item->sizeHint();
qDebug() << "条目宽度:" << size.width();
qDebug() << "条目高度:" << size.height();
2.5.4 关键注意事项(必知!)
- 宽度生效(超级重要!):若 QListWidget 宽度自适应,条目的宽度可能被拉伸,需结合控件固定宽度使用;
- 统一尺寸(超级重要!) :若设置
setUniformItemSizes(true),仅第一个条目的sizeHint生效; - 最小尺寸限制:设置的尺寸小于内容最小显示尺寸时,会自动适配;
- 配合文本对齐 :想让文本对齐效果更明显,需先设置较大的
sizeHint。
2.6 方法六:setSelected () & isSelected ()------ 设置 / 获取条目是否选中
2.6.1 方法的核心定义
setSelected() 是 QListWidgetItem 用于控制单个条目选中状态 的方法 ------ 选中的条目会按照系统或自定义样式高亮显示;isSelected() 是对应的获取方法,用于判断条目是否被选中。
通俗理解:setSelected(true) 就像 "在清单这一行纸上打个勾,或者用荧光笔标亮"------ 别人一眼就能看到这一行被选中了;setSelected(false) 就像 "把勾擦掉,或者把荧光笔的颜色去掉";isSelected() 就像 "看看这一行有没有被标亮"。
这里有几个超级重要的规则,必须牢记:
- 仅在非 "NoSelection" 模式下生效 ------QListWidget 的选择模式由
setSelectionMode()控制,默认是SingleSelection(单选);如果设为NoSelection(无选择),setSelected()无效; - 支持单选 / 多选模式 :
- 单选模式(
SingleSelection):选中一个条目时,之前选中的条目会自动取消选中; - 多选模式(
MultiSelection、ExtendedSelection):可以同时选中多个条目;
- 单选模式(
- 调用 setSelected () 会触发信号 ------ 调用
setSelected(true)或setSelected(false)会触发 QListWidget 的itemSelectionChanged()信号; - 视觉样式可自定义 ------ 选中条目的高亮样式可以通过 QSS 自定义(比如
QListWidget::item:selected { background-color: blue; })。
2.6.2 关联 API 详解(逐词逐句,零模糊)
1. 设置条目是否选中:void setSelected (bool selected)
函数原型:
void QListWidgetItem::setSelected(bool selected);
逐词逐句底层解析:
void:无返回值;QListWidgetItem:::成员函数;setSelected():函数名,"设置是否选中" 的意思;bool selected:入参,selected是true选中,false取消选中(默认)。
参数说明:
selected:true选中条目,false取消选中。
2. 判断条目是否选中:bool isSelected () const
函数原型:
bool QListWidgetItem::isSelected() const;
逐词逐句底层解析:
bool:返回值类型,返回true或false;QListWidgetItem:::成员函数;isSelected():函数名,"是不是被选中了" 的意思;const:常成员函数。
返回值说明:
true表示条目被选中;false表示条目未被选中(默认)。
2.6.3 使用示例
#include <QListWidgetItem>
#include <QAbstractItemView>
// 先设置选择模式为单选(默认也是单选,这里显式设置)
ui->listWidget->setSelectionMode(QAbstractItemView::SingleSelection);
// 添加几个条目
QListWidgetItem* item1 = new QListWidgetItem("条目1");
QListWidgetItem* item2 = new QListWidgetItem("条目2");
ui->listWidget->addItem(item1);
ui->listWidget->addItem(item2);
// 示例1:选中第一个条目
item1->setSelected(true);
// 此时条目1 会高亮显示
// 示例2:判断条目是否选中
if (item1->isSelected()) {
qDebug() << "条目1 被选中了";
}
// 示例3:取消选中
item1->setSelected(false);
// 此时条目1 取消高亮
// 示例4:多选模式下选中多个条目
ui->listWidget->setSelectionMode(QAbstractItemView::MultiSelection); // 切换到多选
item1->setSelected(true);
item2->setSelected(true);
// 此时两个条目都被选中
2.6.4 关键注意事项(必知!)
- 选择模式(超级重要!) :仅在非
NoSelection模式下生效; - 单选 / 多选(超级重要!):单选模式下选中一个会自动取消另一个;
- 信号触发(超级重要!) :调用
setSelected()会触发itemSelectionChanged()信号; - 视觉样式可自定义:通过 QSS 自定义选中高亮样式。
2.7 方法七:setTextAlignment () & textAlignment ()------ 设置 / 获取文本对齐方式
2.7.1 方法的核心定义
setTextAlignment() 是 QListWidgetItem 用于控制文本在条目内部对齐位置 的方法 ------ 你可以设置水平对齐(左对齐、居中、右对齐)和垂直对齐(顶部、居中、底部);textAlignment() 是对应的获取方法。
通俗理解:setTextAlignment() 就像 "把这一行纸上的字摆到什么位置"------ 比如摆到中间、摆到右边、摆到右下角;默认是左对齐 + 垂直居中。
这里有几个超级重要的规则,必须牢记,刻在脑子里:
-
默认对齐方式 ------ 默认是
Qt::AlignLeft | Qt::AlignVCenter(左对齐 + 垂直居中); -
核心枚举值(Qt::Alignment)(超级重要!) :
枚举值 功能说明 Qt::AlignLeft水平左对齐(默认); Qt::AlignRight水平右对齐; Qt::AlignHCenter水平居中; Qt::AlignCenter水平 + 垂直居中(等价于 `AlignHCenter AlignVCenter`); Qt::AlignTop垂直顶部对齐; Qt::AlignBottom垂直底部对齐; Qt::AlignVCenter垂直居中(默认); -
可组合使用 ------ 你可以通过
|(按位或)组合水平和垂直对齐方式,比如Qt::AlignRight | Qt::AlignBottom(右对齐 + 底部对齐); -
需配合 setSizeHint () 效果才明显!(超级重要!说三遍!) :
- 如果条目尺寸刚好包裹内容,文本对齐的效果看不出来;
- 你需要先通过
setSizeHint()给条目设置一个较大的尺寸,让条目内部有多余的空间,对齐效果才会明显;
-
仅针对文本部分------ 文本对齐仅针对文本部分,图标始终显示在文本左侧,不受对齐方式影响。
2.7.2 关联 API 详解(逐词逐句,零模糊)
1. 设置文本对齐方式:void setTextAlignment (int alignment)
函数原型:
void QListWidgetItem::setTextAlignment(int alignment);
逐词逐句底层解析:
void:无返回值;QListWidgetItem:::成员函数;setTextAlignment():函数名,"设置文本对齐方式" 的意思;int alignment:入参,alignment是Qt::Alignment枚举值的组合(用int接收是因为枚举值本质是整数)。
参数说明:
alignment:对齐方式,可组合多个Qt::Alignment枚举值(用|连接)。
2. 获取文本对齐方式:int textAlignment () const
函数原型:
int QListWidgetItem::textAlignment() const;
逐词逐句底层解析:
int:返回值类型,返回对齐方式的组合(整数形式);QListWidgetItem:::成员函数;textAlignment():函数名,"获取文本对齐方式" 的意思;const:常成员函数。
返回值说明:
- 返回
int类型的整数,对应Qt::Alignment枚举值的组合; - 未设置则返回默认值
Qt::AlignLeft | Qt::AlignVCenter。
2.7.3 使用示例
#include <QListWidgetItem>
#include <QSize>
#include <Qt> // 包含 Qt::Alignment 枚举
// 示例1:文本水平居中 + 垂直居中
QListWidgetItem* item1 = new QListWidgetItem("居中对齐");
item1->setSizeHint(QSize(200, 50)); // 先设置较大尺寸,对齐效果才明显!
item1->setTextAlignment(Qt::AlignCenter); // 等价于 AlignHCenter | AlignVCenter
ui->listWidget->addItem(item1);
// 示例2:文本右对齐 + 垂直底部对齐
QListWidgetItem* item2 = new QListWidgetItem("右底对齐");
item2->setSizeHint(QSize(200, 50)); // 先设置较大尺寸!
item2->setTextAlignment(Qt::AlignRight | Qt::AlignBottom); // 组合使用
ui->listWidget->addItem(item2);
2.7.4 关键注意事项(必知!)
- 需配合 setSizeHint () 效果才明显!(超级重要!说三遍!):条目尺寸太小的话,对齐效果看不出来;
- 可组合使用(超级重要!) :通过
|组合水平和垂直对齐方式; - 仅针对文本部分:图标始终在文本左侧,不受影响;
- 默认对齐方式:左对齐 + 垂直居中。
示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QListWidgetItem>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//OK,大家,接下来我们来学习多元素控件,即一个控件中包含多个元素
//那么我们先学习QListWidget控件,这个控件其实就像是一个列表一样,把要显示的条目都显示出来
//然后支持添加删除等等,说白了其实就像是一个一维数组一样~~~
//那么由于我们去向QListWidget控件添加或者查找或者删除条目的时候,需要设置QListWidget控件的条目类
//所以本文件我们就先来血洗QListWidgetItem类,其实它是很简单的,和我们之前学习的单元素控件算是差不多的哦~~
/**
* @class QListWidgetItem
* @brief Qt中QListWidget控件的核心元素类,表征列表中的单个条目
* @details QListWidgetItem是QListWidget的最小组成单元,核心由**文本+图标**构成,支持字体、显示状态、尺寸、选中状态、文本对齐方式等个性化配置;
* 每个条目可独立设置样式和状态,是实现列表项自定义展示与交互的基础。
*
* 【核心特征】
* 1. 基础展示:支持文本、图标双元素展示,是列表项的核心视觉内容;
* 2. 样式定制:可单独设置字体(大小/粗细/颜色)、文本对齐方式;
* 3. 状态控制:支持隐藏/显示、选中/未选中状态切换;
* 4. 尺寸适配:可自定义条目尺寸,适配不同视觉需求。
*/
// ============================== 核心方法详解 ==============================
/**
* @fn void QListWidgetItem::setFont(const QFont &font)
* @brief 设置列表项的字体样式
* @details 该方法用于自定义单个列表项的字体(大小、粗细、颜色、字体家族等),优先级高于QListWidget的全局字体设置;
* 未单独设置时,继承父控件QListWidget的字体样式。
*
* @参数说明:
* @param font - QFont类型,包含字体家族、大小、粗细、下划线等样式属性。
*
* 【关联API】
* 1. QFont font() const → 获取当前列表项的字体样式;
* 2. QFont QListWidget::font() const → 获取列表控件的全局字体(未单独设置时继承)。
*
* @使用示例:
* // 创建列表项并设置字体(微软雅黑、14号、粗体)
* QListWidgetItem* item = new QListWidgetItem("自定义字体条目");
* QFont font("Microsoft YaHei", 14, QFont::Bold);
* item->setFont(font);
* ui->listWidget->addItem(item);
*
* 【关键注意事项】
* 1. 优先级:单个条目字体 > QListWidget全局字体 > 应用程序默认字体;
* 2. 颜色设置:QFont仅控制字体样式,文本颜色需通过setForeground()设置(如item->setForeground(Qt::red));
* 3. 动态生效:设置后立即刷新列表项视觉效果,无需额外刷新控件。
*/
/**
* @fn void QListWidgetItem::setIcon(const QIcon &icon)
* @brief 设置列表项的显示图标
* @details 该方法为列表项添加/修改图标,图标会显示在文本左侧(默认布局),是实现"图标+文本"列表项的核心方法;
* 未设置时列表项仅显示文本,无图标。
*
* @参数说明:
* @param icon - QIcon类型,支持本地图片、资源文件、系统图标等多种图标来源。
*
* 【关联API】
* 1. QIcon icon() const → 获取当前列表项的图标;
* 2. void QListWidget::setIconSize(const QSize &size) → 设置列表控件中所有图标的统一显示尺寸。
*
* @使用示例:
* // 方式1:使用资源文件图标
* QListWidgetItem* item1 = new QListWidgetItem("资源图标");
* item1->setIcon(QIcon(":/images/icon.png"));
* ui->listWidget->addItem(item1);
*
* // 方式2:使用系统图标
* QListWidgetItem* item2 = new QListWidgetItem("系统图标");
* item2->setIcon(QApplication::style()->standardIcon(QStyle::SP_FileIcon));
* ui->listWidget->addItem(item2);
*
* // 设置图标显示尺寸(全局)
* ui->listWidget->setIconSize(QSize(24, 24));
*
* 【关键注意事项】
* 1. 尺寸控制:图标显示尺寸由QListWidget::setIconSize()全局控制,单个条目无法单独设置;
* 2. 资源路径:使用资源文件时需确保路径正确(以:/开头),本地图片需传入完整路径;
* 3. 透明适配:QIcon自动适配不同显示状态(选中/未选中),也可通过QIcon::addPixmap()自定义状态图标。
*/
/**
* @fn void QListWidgetItem::setHidden(bool hidden)
* @brief 设置列表项是否隐藏
* @details 该方法控制单个列表项的显示/隐藏状态,隐藏的条目不会在列表中显示,也不参与列表布局计算;
* 区别于setDisabled()(禁用仅灰显,仍占用布局空间),隐藏会完全移除视觉展示。
*
* @参数说明:
* @param hidden - bool类型,true=隐藏条目,false=显示条目(默认)。
*
* 【关联API】
* 1. bool isHidden() const → 判断当前列表项是否处于隐藏状态;
* 2. void QListWidgetItem::setDisabled(bool disabled) → 设置条目禁用(灰显,仍显示)。
*
* @使用示例:
* // 隐藏指定条目
* QListWidgetItem* item = ui->listWidget->item(0); // 获取第0个条目
* item->setHidden(true); // 隐藏
*
* // 显示条目
* item->setHidden(false); // 显示
*
* 【关键注意事项】
* 1. 布局影响:隐藏的条目不占用列表控件的布局空间,列表会自动重新排列剩余条目;
* 2. 状态保留:隐藏仅影响显示,条目的文本、图标、选中状态等数据完全保留;
* 3. 交互屏蔽:隐藏的条目无法被选中、点击,也不会响应任何交互事件。
*/
/**
* @fn void QListWidgetItem::setSizeHint(const QSize &size)
* @brief 设置列表项的尺寸提示(自定义条目大小)
* @details 该方法为单个列表项设置固定尺寸,优先级高于QListWidget的默认条目尺寸;
* 未设置时,条目尺寸由内容(文本+图标)和控件样式自动计算。
*
* @参数说明:
* @param size - QSize类型,width为条目宽度,height为条目高度(单位:像素)。
*
* 【关联API】
* 1. QSize sizeHint() const → 获取当前列表项的尺寸提示;
* 2. void QListWidget::setUniformItemSizes(bool uniform) → 设置所有条目是否使用统一尺寸(true时仅第一个条目的sizeHint生效)。
*
* @使用示例:
* // 创建条目并设置固定尺寸(宽200px,高50px)
* QListWidgetItem* item = new QListWidgetItem("自定义尺寸条目");
* item->setSizeHint(QSize(200, 50));
* ui->listWidget->addItem(item);
*
* 【关键注意事项】
* 1. 宽度生效:若QListWidget的resizeMode为AdjustToContents,宽度可能被内容拉伸,需结合控件固定宽度使用;
* 2. 统一尺寸:若设置setUniformItemSizes(true),所有条目会使用第一个条目的sizeHint,单独设置无效;
* 3. 最小尺寸:设置的尺寸小于内容最小显示尺寸时,会自动适配为内容最小尺寸。
*/
/**
* @fn void QListWidgetItem::setSelected(bool selected)
* @brief 设置列表项是否被选中
* @details 该方法控制单个列表项的选中状态,选中的条目会按照系统/自定义样式高亮显示;
* 支持单选/多选模式(由QListWidget::setSelectionMode()控制)。
*
* @参数说明:
* @param selected - bool类型,true=选中条目,false=取消选中(默认)。
*
* 【关联API】
* 1. bool isSelected() const → 判断当前列表项是否被选中;
* 2. void QListWidget::setSelectionMode(QAbstractItemView::SelectionMode mode) → 设置列表选择模式(单选/多选/无选择);
* 3. QListWidgetItem* QListWidget::currentItem() const → 获取列表当前选中的条目(单选模式)。
*
* @使用示例:
* // 1. 设置单选模式并选中第一个条目
* ui->listWidget->setSelectionMode(QAbstractItemView::SingleSelection);
* QListWidgetItem* item1 = new QListWidgetItem("选中条目");
* ui->listWidget->addItem(item1);
* item1->setSelected(true);
*
* // 2. 多选模式下选中多个条目
* ui->listWidget->setSelectionMode(QAbstractItemView::MultiSelection);
* QListWidgetItem* item2 = new QListWidgetItem("多选条目1");
* QListWidgetItem* item3 = new QListWidgetItem("多选条目2");
* ui->listWidget->addItem(item2);
* ui->listWidget->addItem(item3);
* item2->setSelected(true);
* item3->setSelected(true);
*
* 【关键注意事项】
* 1. 选择模式:仅在非"NoSelection"模式下,选中状态才会生效;
* 2. 信号触发:调用setSelected()会触发QListWidget::itemSelectionChanged()信号;
* 3. 视觉样式:选中高亮样式可通过QSS自定义(如QListWidget::item:selected)。
*/
/**
* @fn void QListWidgetItem::setText(const QString &text)
* @brief 设置列表项的显示文本
* @details 该方法是列表项最基础的配置,设置条目核心显示文本,支持普通字符串、富文本(HTML格式);
* 文本是列表项的核心标识,未设置时条目为空。
*
* @参数说明:
* @param text - QString类型,列表项要显示的文本内容(支持UTF-8编码,可包含中文、特殊字符)。
*
* 【关联API】
* 1. QString text() const → 获取当前列表项的显示文本;
* 2. void QListWidgetItem::setToolTip(const QString &tip) → 设置文本提示(鼠标悬浮时显示)。
*
* @使用示例:
* // 1. 设置普通文本
* QListWidgetItem* item1 = new QListWidgetItem("普通文本条目");
* ui->listWidget->addItem(item1);
*
* // 2. 设置富文本(带颜色、加粗)
* QListWidgetItem* item2 = new QListWidgetItem();
* item2->setText("<font color='red'><b>富文本条目</b></font>");
* ui->listWidget->addItem(item2);
*
* 【关键注意事项】
* 1. 富文本支持:仅基础HTML标签(<b>/<i>/<font>等),复杂标签可能无法渲染;
* 2. 文本截断:文本过长时,列表项会自动截断并显示省略号(可通过setSizeHint扩大尺寸避免);
* 3. 编码适配:确保文本为UTF-8编码,避免中文乱码(Qt默认支持,需注意文件编码)。
*/
/**
* @fn void QListWidgetItem::setTextAlignment(int alignment)
* @brief 设置列表项文本的对齐方式
* @details 该方法控制文本在列表项内部的对齐位置(水平+垂直),默认对齐方式为Qt::AlignLeft | Qt::AlignVCenter(左对齐+垂直居中);
* 对齐效果受条目尺寸(sizeHint)影响,需配合尺寸设置达到预期效果。
*
* 【核心枚举值(Qt::Alignment)】
* | 枚举值 | 功能说明 |
* |-----------------------|--------------------------------------------------------------------------|
* | Qt::AlignLeft | 水平左对齐(默认); |
* | Qt::AlignRight | 水平右对齐; |
* | Qt::AlignHCenter | 水平居中; |
* | Qt::AlignCenter | 水平+垂直居中(等价于AlignHCenter | AlignVCenter); |
* | Qt::AlignTop | 垂直顶部对齐; |
* | Qt::AlignBottom | 垂直底部对齐; |
* | Qt::AlignVCenter | 垂直居中(默认); |
*
* @参数说明:
* @param alignment - int类型,可组合多个Qt::Alignment枚举值(用|连接)。
*
* 【关联API】
* 1. int textAlignment() const → 获取当前列表项的文本对齐方式。
*
* @使用示例:
* // 1. 文本水平居中+垂直居中
* QListWidgetItem* item1 = new QListWidgetItem("居中对齐");
* item1->setTextAlignment(Qt::AlignCenter);
* item1->setSizeHint(QSize(200, 50)); // 扩大尺寸,对齐效果更明显
* ui->listWidget->addItem(item1);
*
* // 2. 文本右对齐+垂直底部对齐
* QListWidgetItem* item2 = new QListWidgetItem("右底对齐");
* item2->setTextAlignment(Qt::AlignRight | Qt::AlignBottom);
* item2->setSizeHint(QSize(200, 50));
* ui->listWidget->addItem(item2);
*
* 【关键注意事项】
* 1. 组合使用:对齐方式可通过|组合(如Qt::AlignHCenter | Qt::AlignTop);
* 2. 尺寸影响:条目尺寸过小时,对齐效果不明显,需配合setSizeHint扩大尺寸;
* 3. 图标兼容:文本对齐仅针对文本部分,图标始终显示在文本左侧(不受对齐方式影响)。
*/
QListWidgetItem* item=new QListWidgetItem();
item->setText("this is a item");
QFont font;
font.setFamily("黑体");
font.setBold(true);
item->setFont(font);
item->setIcon(QIcon("C:\\Users\\Win\\Desktop\\b_17576d8be766c15b868aa7e1da548e34.jpg"));
item->setTextAlignment(Qt::AlignLeft);
}
Widget::~Widget()
{
delete ui;
}
第三章 QListWidget 核心属性详解(一)
讲完了 QListWidgetItem 类,我们接下来讲 QListWidget 的核心属性 。我们首先讲第一部分:currentRow(当前选中行号)、count(总行数)、itemAlignment(条目整体对齐)、selectRectVisible(选中矩形可见)、spacing(条目间距)。

3.1 属性一:currentRow------ 当前选中的是第几行?
3.1.1 属性的核心定义
currentRow 是 QListWidget 用于表征当前激活选中条目的行号的属性 ------ 行号从 0 开始计数(第一行是 0,第二行是 1,以此类推),无选中条目时值为 -1。
通俗理解:currentRow 就像 "清单上当前被标亮的是第几行"------ 注意是从 0 开始数的,不是从 1 开始!如果没有任何一行被标亮,它就是 -1。
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 行号从 0 开始计数!(超级重要!说三遍!) :
- 第一行的行号是 0,第二行是 1,第三行是 2,...,第 N 行是 N-1;
- 用户视角的 "第 1 行" 对应代码里的
row=0,这点新手非常容易搞错!
- 无选中条目时值为 -1 :如果列表为空,或者没有任何条目被选中,
currentRow返回 -1; - 超出范围设置会取消选中 :如果你调用
setCurrentRow(row)时,row不在有效范围[0, count()-1]内,会取消所有选中,currentRow变为 -1; - 联动 currentItem :
currentRow和currentItem是一一对应的 ------currentItem()对应的行号就是currentRow(),修改其中一个,另一个会自动更新; - 修改会触发信号 :设置有效行号时会触发
currentRowChanged()和currentItemChanged()信号。
3.1.2 关联 API 详解(逐词逐句,零模糊)
currentRow 属性有两个关联的 API:
1. 获取当前选中行号:int currentRow () const
函数原型:
int QListWidget::currentRow() const;
逐词逐句底层解析:
int:返回值类型,返回当前选中的行号;QListWidget:::成员函数;currentRow():函数名,"获取当前行号" 的意思;const:常成员函数。
返回值说明:
- 返回
int类型的整数; - 有效范围:
0 ≤ row < count(); - 无选中时返回
-1。
2. 设置当前选中行号:void setCurrentRow (int row)
函数原型:
void QListWidget::setCurrentRow(int row);
逐词逐句底层解析:
void:无返回值;QListWidget:::成员函数;setCurrentRow():函数名,"设置当前行号" 的意思;int row:入参,目标行号。
参数说明:
row:目标行号,int类型;- 有效范围:
0 ≤ row < count(); - 超出范围则取消所有选中,
currentRow变为-1。
3.1.3 使用示例
#include <QDebug>
// 先添加几个条目
ui->listWidget->addItem("条目1"); // 行号 0
ui->listWidget->addItem("条目2"); // 行号 1
ui->listWidget->addItem("条目3"); // 行号 2
// 示例1:设置选中第 2 行(用户视角),对应代码行号 1
ui->listWidget->setCurrentRow(1);
// 示例2:获取当前选中行号并打印
int selectedRow = ui->listWidget->currentRow();
if (selectedRow == -1) {
qDebug() << "当前无选中项";
} else {
qDebug() << "当前选中行号(代码):" << selectedRow;
qDebug() << "当前选中行号(用户):" << selectedRow + 1; // 行号+1 适配用户习惯
}
// 示例3:设置超出范围的行号(取消选中)
ui->listWidget->setCurrentRow(100); // 超出范围
qDebug() << "当前选中行号:" << ui->listWidget->currentRow(); // 输出 -1
3.1.4 关键注意事项(必知!)
- 行号从 0 开始!(超级重要!说三遍!):用户视角的第 1 行对应代码的 0;
- 无选中返回 -1(超级重要!):使用前需判断是否为 -1;
- 超出范围取消选中:设置无效行号会取消所有选中;
- 联动 currentItem:二者一一对应;
- 修改触发信号 :设置有效行号会触发
currentRowChanged()和currentItemChanged()。
3.2 属性二:count------ 一共有多少行?(只读)
3.2.1 属性的核心定义
count 是 QListWidget 的只读属性------ 它实时统计列表中 QListWidgetItem 的总数,默认值为 0(空列表)。
通俗理解:count 就像 "数一数清单里一共有多少行纸"------ 你加一行,它就加 1;你删一行,它就减 1;它是实时更新的,不用你手动数。
这里有几个超级重要的规则,必须牢记:
- 只读特性!(超级重要!) :你无法直接通过赋值修改
count(比如ui->listWidget->count = 10是错误的),只能通过addItem、insertItem、takeItem等方法间接变更; - 实时更新:增删条目后立即生效,无需手动刷新;
- 有效行号上限 :有效行号的范围是
[0, count()-1]------ 遍历列表时常用for(int i=0; i<count(); i++); - 快速判断是否为空 :可以用
count() == 0判断列表是否为空,也可以用更便捷的isEmpty()方法(等价于count() == 0)。
3.2.2 关联 API 详解(逐词逐句,零模糊)
count 属性有两个关联的 API:
1. 获取列表总行数:int count () const
函数原型:
int QListWidget::count() const;
逐词逐句底层解析:
int:返回值类型,返回总行数;QListWidget:::成员函数;count():函数名,"获取总数" 的意思;const:常成员函数。
返回值说明:
- 返回
int类型的整数; - 空列表返回 0。
2. 【便捷】快速判断列表是否为空:bool isEmpty () const
函数原型:
bool QListWidget::isEmpty() const;
逐词逐句底层解析:
bool:返回值类型,返回true或false;QListWidget:::成员函数;isEmpty():函数名,"是不是空的" 的意思;const:常成员函数。
返回值说明:
true表示列表为空(count() == 0);false表示列表不为空。
3.2.3 使用示例
#include <QDebug>
// 先添加几个条目
ui->listWidget->addItem("条目1");
ui->listWidget->addItem("条目2");
ui->listWidget->addItem("条目3");
// 示例1:统计总行数并打印
int total = ui->listWidget->count();
qDebug() << "列表总行数:" << total; // 输出 3
// 示例2:判断列表是否为空(两种方式)
// 方式1:用 count()
if (ui->listWidget->count() == 0) {
qDebug() << "列表为空";
} else {
qDebug() << "列表不为空";
}
// 方式2:用 isEmpty()(更便捷!推荐!)
if (ui->listWidget->isEmpty()) {
qDebug() << "列表为空";
} else {
qDebug() << "列表不为空";
}
// 示例3:遍历所有条目(常用!)
for (int i = 0; i < ui->listWidget->count(); ++i) {
QListWidgetItem* item = ui->listWidget->item(i);
if (item) {
qDebug() << "第" << i+1 << "行:" << item->text();
}
}
3.2.4 关键注意事项(必知!)
- 只读特性!(超级重要!):无法直接赋值修改,只能通过增删条目间接变更;
- 实时更新:增删条目后立即生效;
- 有效行号上限 :
[0, count()-1]; - 推荐用 isEmpty () :比
count() == 0更便捷、更直观。
3.3 属性三:itemAlignment------ 条目整体在控件中怎么对齐?
3.3.1 属性的核心定义
itemAlignment 是 QListWidget 用于控制所有条目在列表控件内整体对齐位置 的属性 ------ 注意!它是 "条目在控件中对齐",不是"文本在条目中对齐"(那是 QListWidgetItem::setTextAlignment ())!
通俗理解:itemAlignment 就像 "把清单里的所有行纸作为一个整体,摆到清单本的什么位置"------ 比如摆到中间、摆到右边;而 setTextAlignment() 是 "把某一行纸上的字摆到这一行的什么位置"------ 这两个是不同层级的对齐,一定要区分开!
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 层级区别!(超级重要!说三遍!) :
QListWidget::itemAlignment:条目在控件中的整体对齐;QListWidgetItem::setTextAlignment():文本在条目中的对齐;- 这两个是完全不同的,不要搞混!
- 默认对齐方式 ------ 默认是
Qt::AlignLeft | Qt::AlignTop(左对齐 + 顶部对齐); - 核心枚举值和之前一样 ------ 用的还是
Qt::Alignment枚举,和setTextAlignment()的枚举值一样; - 需控件尺寸大于条目总尺寸效果才明显!(超级重要!) :
- 如果 QListWidget 的尺寸刚好包裹所有条目,整体对齐的效果看不出来;
- 你需要先给 QListWidget 设置一个较大的固定尺寸,让控件内部有多余的空间,对齐效果才会明显;
- 可组合使用 ------ 同样通过
|组合水平和垂直对齐方式。
3.3.2 关联 API 详解(逐词逐句,零模糊)
1. 获取条目整体对齐方式:Qt::Alignment itemAlignment () const
函数原型:
Qt::Alignment QListWidget::itemAlignment() const;
逐词逐句底层解析:
Qt::Alignment:返回值类型,返回对齐方式;QListWidget:::成员函数;itemAlignment():函数名,"获取条目整体对齐方式" 的意思;const:常成员函数。
返回值说明:
- 返回
Qt::Alignment枚举值的组合; - 默认返回
Qt::AlignLeft | Qt::AlignTop。
2. 设置条目整体对齐方式:void setItemAlignment (Qt::Alignment alignment)
函数原型:
void QListWidget::setItemAlignment(Qt::Alignment alignment);
逐词逐句底层解析:
void:无返回值;QListWidget:::成员函数;setItemAlignment():函数名,"设置条目整体对齐方式" 的意思;Qt::Alignment alignment:入参,对齐方式。
参数说明:
alignment:对齐方式,Qt::Alignment枚举值的组合。
3.3.3 使用示例
#include <Qt>
// 先给 QListWidget 设置一个较大的固定尺寸(对齐效果才明显!)
ui->listWidget->setFixedSize(400, 300); // 宽 400,高 300
// 添加几个条目
ui->listWidget->addItem("条目1");
ui->listWidget->addItem("条目2");
ui->listWidget->addItem("条目3");
// 设置所有条目在控件中水平+垂直居中
ui->listWidget->setItemAlignment(Qt::AlignCenter);
3.3.4 关键注意事项(必知!)
- 层级区别!(超级重要!说三遍!) :和
QListWidgetItem::setTextAlignment()是不同层级的对齐! - 需控件尺寸大于条目总尺寸效果才明显!(超级重要!);
- 默认对齐方式:左对齐 + 顶部对齐;
- 可组合使用 :通过
|组合水平和垂直对齐方式。
3.4 属性四:selectRectVisible------ 选中条目的矩形框要不要显示?
3.4.1 属性的核心定义
selectRectVisible 是 QListWidget 用于控制选中条目周围的高亮矩形框显隐 的属性 ------ 默认值为 true(可见);设为 false 时,选中条目仍会触发选中信号,但无视觉矩形框高亮,可配合 QSS 自定义选中样式。
通俗理解:selectRectVisible 就像 "要不要显示选中条目的那个虚线框 / 高亮框"------ 如果设为 false,就不显示那个框,但条目还是被选中的,你可以通过 QSS 自定义其他选中样式(比如只改变文本颜色)。
这里有几个超级重要的规则,必须牢记:
- 默认值为 true(可见)------ 刚创建 QListWidget 时,选中条目周围会有系统默认的高亮矩形框;
- 仅视觉影响,不改变选中逻辑!(超级重要!) :
- 隐藏矩形框不改变选中逻辑、行号 / 条目对象关联,也不影响选中信号触发;
- 条目还是被选中的,只是看不到那个框而已;
- 样式覆盖(超级重要!) :
- 若通过 QSS 自定义了
QListWidget::item:selected样式,该属性可能被覆盖,以 QSS 样式为准; - 比如你用 QSS 设置了选中条目的背景色,哪怕
selectRectVisible=false,背景色还是会显示;
- 若通过 QSS 自定义了
- 交互兼容------ 即使隐藏矩形框,条目仍可被点击 / 选中 / 双击,所有交互功能正常。
3.4.2 关联 API 详解(逐词逐句,零模糊)
1. 判断选中矩形框是否可见:bool isSelectRectVisible () const
函数原型:
bool QListWidget::isSelectRectVisible() const;
逐词逐句底层解析:
bool:返回值类型,返回true或false;QListWidget:::成员函数;isSelectRectVisible():函数名,"选中矩形框是不是可见" 的意思;const:常成员函数。
返回值说明:
true表示选中矩形框可见(默认);false表示选中矩形框隐藏。
2. 设置选中矩形框显隐:void setSelectRectVisible (bool visible)
函数原型:
void QListWidget::setSelectRectVisible(bool visible);
逐词逐句底层解析:
void:无返回值;QListWidget:::成员函数;setSelectRectVisible():函数名,"设置选中矩形框显隐" 的意思;bool visible:入参,visible是true可见,false隐藏。
参数说明:
visible:true显示选中矩形框,false隐藏。
3.4.3 使用示例
#include <QListWidgetItem>
// 添加条目
ui->listWidget->addItem("条目1");
// 隐藏默认选中矩形框
ui->listWidget->setSelectRectVisible(false);
// 选中第一个条目
ui->listWidget->setCurrentRow(0);
// 此时条目被选中,但没有系统默认的矩形框高亮
// 你可以通过 QSS 自定义选中样式,比如只改变文本颜色
3.4.4 关键注意事项(必知!)
- 仅视觉影响(超级重要!):不改变选中逻辑和信号触发;
- 样式覆盖(超级重要!):QSS 自定义样式可能覆盖该属性;
- 交互兼容:隐藏后所有交互功能正常;
- 默认值为 true。
3.5 属性五:spacing------ 条目之间的间距是多少?
3.5.1 属性的核心定义
spacing 是 QListWidget 用于控制相邻条目间间距的属性 ------ 单位是像素,默认值为 0(无间距)。
通俗理解:spacing 就像 "清单里每一行纸之间的空隙"------ 你设置 5 像素,每两行之间就空 5 像素;设置 10 像素,就空 10 像素;空隙大一点,看起来更舒服。
这里有几个超级重要的规则,必须牢记:
- 单位是像素------ 间距的单位是像素,数值越大,条目间的空隙越大;
- 默认值为 0(无间距)------ 刚创建 QListWidget 时,条目之间是紧挨着的,没有空隙;
- 开启换行(isWrapping=true)时同时控制水平和垂直间距 :
- 未开启换行时(默认,纵向单列),仅控制垂直间距(上下条目之间的空隙);
- 开启换行后(多列流式布局),同时控制水平间距 (左右条目之间的空隙)和垂直间距;
- 负值自动修正为 0------ 如果你设置的间距是负数,Qt 会自动修正为 0,不会出现条目重叠;
- 布局影响------ 间距会增加列表的整体尺寸,需结合控件大小适配,避免出现滚动条或显示不全。
3.5.2 关联 API 详解(逐词逐句,零模糊)
1. 获取条目间距:int spacing () const
函数原型:
int QListWidget::spacing() const;
逐词逐句底层解析:
int:返回值类型,返回间距(像素);QListWidget:::成员函数;spacing():函数名,"获取间距" 的意思;const:常成员函数。
返回值说明:
- 返回
int类型的整数; - 单位是像素;
- 默认返回 0。
2. 设置条目间距:void setSpacing (int space)
函数原型:
void QListWidget::setSpacing(int space);
逐词逐句底层解析:
void:无返回值;QListWidget:::成员函数;setSpacing():函数名,"设置间距" 的意思;int space:入参,space是间距(像素)。
参数说明:
space:间距,int类型,单位是像素;- 建议设置为 ≥ 0 的整数;
- 负值自动修正为 0。
3.5.3 使用示例
// 添加几个条目
ui->listWidget->addItem("条目1");
ui->listWidget->addItem("条目2");
ui->listWidget->addItem("条目3");
// 设置条目间距为 8 像素(提升视觉舒适度)
ui->listWidget->setSpacing(8);
// 此时每两个条目之间空 8 像素,看起来更舒服
3.5.4 关键注意事项(必知!)
- 单位是像素;
- 开启换行时同时控制水平和垂直间距(超级重要!);
- 负值自动修正为 0;
- 布局影响:间距会增加列表整体尺寸;
- 默认值为 0。
示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QListWidget>
#include <QListWidgetItem>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//OK,本文件我们就来学习QListWidget控件的currentRow、count、spacing、itemAlignment属性
//那么count属性很简单,是获取到QListWidget控件中有多少个条目~~
//而currentRow属性呢,则是获取到用户选择的是哪一行条目
//spacing属性,则是设置说QListWidget控件里的每个条目之间的距离
//最后的itemAlignment属性,我们也很属性了,就是设置QListWidget控件中的条目的是要居哪边呢??
/**
* @class QListWidget
* @brief Qt中纵向列表展示控件的核心属性(行选中/行数/对齐/选中矩形/间距)
* @details 以下属性聚焦QListWidget的基础状态管理与视觉布局,currentRow/count控制列表选中状态和数量统计,itemAlignment/selectRectVisible/spacing定制列表视觉展示效果,是列表控件最常用的核心属性。
*/
// ============================== 核心属性详解 ==============================
/**
* @property QListWidget::currentRow
* @brief QListWidget当前被选中条目的行号属性
* @details 表征列表中当前激活选中条目的行号,行号从0开始计数(第一行=0),无选中条目时值为-1;修改该属性会触发currentRowChanged()信号,是控制/获取选中行的核心属性。
*
* 【关联API详解】
* 1. int currentRow() const → 获取当前选中行号(无选中返回-1);
* 2. void setCurrentRow(int row) → 设置指定行号为选中行(行号超出范围则取消选中)。
*
* @使用示例:
* // 获取当前选中行号并打印
* int selectedRow = ui->listWidget->currentRow();
* qDebug() << "当前选中行:" << (selectedRow == -1 ? "无" : QString::number(selectedRow + 1)); // 行号+1适配用户习惯
*
* // 设置选中第2行(索引1)
* ui->listWidget->setCurrentRow(1);
*
* 【关键注意事项】
* 1. 行号规则:有效行号范围为[0, count()-1],超出范围设置会取消所有选中,currentRow变为-1;
* 2. 联动选中:修改currentRow会同步更新currentItem(选中条目对象),反之修改currentItem也会更新currentRow;
* 3. 信号触发:设置有效行号时会触发currentRowChanged()和currentItemChanged()信号。
*/
/**
* @property QListWidget::count
* @brief QListWidget列表中条目总行数属性(只读)
* @details 只读属性,实时统计列表中QListWidgetItem的总数,默认值为0(空列表);增删条目时自动更新,是判断列表是否为空、遍历列表的核心依据。
*
* 【关联API详解】
* 1. int count() const → 获取列表总行数;
* 2. bool isEmpty() const → 快速判断列表是否为空(等价于count() == 0)。
*
* @使用示例:
* // 统计总行数并判断是否为空
* int total = ui->listWidget->count();
* if (ui->listWidget->isEmpty()) {
* qDebug() << "列表为空";
* } else {
* qDebug() << "列表总行数:" << total;
* }
*
* 【关键注意事项】
* 1. 只读特性:无法直接赋值修改,仅通过addItem/insertItem/takeItem等方法间接变更;
* 2. 实时更新:增删条目后立即生效,无需手动刷新;
* 3. 行号关联:有效行号上限为count()-1,遍历列表时常用for(int i=0; i<count(); i++)。
*/
/**
* @property QListWidget::itemAlignment
* @brief QListWidget列表条目整体的对齐方式属性
* @details 控制所有条目在列表控件内的整体对齐位置(水平+垂直),区别于单个条目内文本的对齐(setTextAlignment),默认值为Qt::AlignLeft | Qt::AlignTop。
*
* 【核心对齐枚举值】
* | 枚举值 | 说明 |
* |----------------|----------------------|
* | Qt::AlignLeft | 水平左对齐(默认)|
* | Qt::AlignHCenter| 水平居中 |
* | Qt::AlignRight | 水平右对齐 |
* | Qt::AlignTop | 垂直顶部对齐(默认)|
* | Qt::AlignVCenter| 垂直居中 |
* | Qt::AlignCenter| 水平+垂直居中 |
*
* 【关联API详解】
* 1. Qt::Alignment itemAlignment() const → 获取条目整体对齐方式;
* 2. void setItemAlignment(Qt::Alignment alignment) → 设置条目整体对齐方式。
*
* @使用示例:
* // 设置所有条目在列表中水平+垂直居中
* ui->listWidget->setItemAlignment(Qt::AlignCenter);
* ui->listWidget->setFixedSize(300, 200); // 固定控件尺寸,对齐效果更明显
*
* 【关键注意事项】
* 1. 层级区别:该属性是"条目在控件中对齐",而非"文本在条目中对齐";
* 2. 视觉适配:控件尺寸需大于条目总尺寸,才能体现明显的对齐效果;
* 3. 组合使用:可通过|组合对齐方式(如Qt::AlignHCenter | Qt::AlignBottom)。
*/
/**
* @property QListWidget::selectRectVisible
* @brief QListWidget选中条目矩形框是否可见的属性
* @details 控制选中条目周围的高亮矩形框显隐,默认值为true(可见);设为false时,选中条目仍会触发选中信号,但无视觉矩形框高亮,可配合QSS自定义选中样式。
*
* 【关联API详解】
* 1. bool isSelectRectVisible() const → 判断选中矩形框是否可见;
* 2. void setSelectRectVisible(bool visible) → 设置选中矩形框显隐。
*
* @使用示例:
* // 隐藏选中矩形框,仅通过文本颜色区分选中状态
* ui->listWidget->setSelectRectVisible(false);
* // 自定义选中条目文本颜色
* QListWidgetItem* item = ui->listWidget->item(0);
* if (item) item->setForeground(Qt::red);
*
* 【关键注意事项】
* 1. 仅视觉影响:隐藏矩形框不改变选中逻辑和信号触发;
* 2. 样式覆盖:若通过QSS自定义了QListWidget::item:selected样式,该属性可能被覆盖;
* 3. 交互兼容:隐藏后条目仍可被选中/点击,不影响交互功能。
*/
/**
* @property QListWidget::spacing
* @brief QListWidget列表条目之间的间距属性(像素)
* @details 控制相邻条目间的水平/垂直间距,默认值为0(无间距);未开启换行时仅控制垂直间距,开启换行(isWrapping=true)时同时控制水平和垂直间距。
*
* 【关联API详解】
* 1. int spacing() const → 获取条目间距(像素);
* 2. void setSpacing(int space) → 设置条目间距(负值自动修正为0)。
*
* @使用示例:
* // 设置条目间距为8像素,提升视觉舒适度
* ui->listWidget->setSpacing(8);
*
* 【关键注意事项】
* 1. 单位:间距单位为像素,数值越大条目间空隙越大;
* 2. 换行适配:开启wrapping时,spacing同时控制行内水平间距和行间垂直间距;
* 3. 布局影响:间距会增加列表整体尺寸,需结合控件大小适配。
*/
QListWidget* lw=new QListWidget(this);
lw->setGeometry(100,100,300,300);
//注意,严格注意,我们创建的QListWidgetItem对象,不能是栈上的对象,必须要用new出来的QListWidgetItem
//否则代码结束后,这些局部对象会被自动销毁,QListWidget 里保存的指针就变成了无效地址,所以界面上看不到这些条目。
QListWidgetItem* item1=new QListWidgetItem("1");
lw->addItem(item1);
QListWidgetItem* item2=new QListWidgetItem("2");
lw->addItem(item2);
QListWidgetItem* item3=new QListWidgetItem("3");
lw->addItem(item3);
//我们也可以直接使用addItem方法,直接传入字符串,没有什么特殊要求的话,直接传入字符串还是最方便的
lw->addItem("4");
int count=lw->count();
lw->setSpacing(5);
lw->setItemAlignment(Qt::AlignLeft);
}
Widget::~Widget()
{
delete ui;
}
第四章 QListWidget 核心属性详解(二)
讲完了第一部分属性,我们接下来讲第二部分:sortingEnabled(是否允许自动排序)、isWrapping(是否允许换行)。
4.1 属性六:sortingEnabled------ 要不要自动排序?
4.1.1 属性的核心定义
sortingEnabled 是 QListWidget 用于控制列表是否按条目文本内容自动升序排序 的属性 ------ 默认值为 false(不排序);设为 true 时,新增 / 修改条目文本、插入条目都会触发自动排序,条目行号会重新分配。
通俗理解:sortingEnabled 就像 "清单的自动排序开关"------ 如果开关打开,你每加一行、每改一行的字,清单都会自动按文字顺序重新排列;如果开关关闭,条目就按你添加的顺序排列,不会动。
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 默认值为 false(不排序)------ 刚创建 QListWidget 时,条目按添加顺序排列;
- 排序规则(超级重要!) :
- 默认按文本的 Unicode 编码升序排列;
- 顺序大致是:数字 < 字母 < 中文;
- 中文按拼音或 Unicode 编码排序(取决于系统和 Qt 版本);
- 开启后新增 / 修改 / 插入都会触发自动排序 :
- 设为
true后,调用addItem()、insertItem()、修改条目文本(item->setText())都会触发自动排序; - 条目行号会重新分配,原有的行号会失效!
- 设为
- 行号变化(超级重要!) :
- 排序后原行号失效,条目行号重新分配;
- 如果你之前保存了某个行号,排序后可能对应的不是同一个条目了!
- 性能影响(超级重要!) :
- 大量条目(如 1000+)开启自动排序会轻微影响增删效率;
- 建议批量增删条目后再开启自动排序,或者批量增删时先关闭,增删完再开启并手动排序;
- 手动排序(超级重要!) :
- 你可以通过
sortItems()方法手动触发排序,无需开启sortingEnabled; sortItems()可以指定升序(Qt::AscendingOrder)或降序(Qt::DescendingOrder)。
- 你可以通过
4.1.2 关联 API 详解(逐词逐句,零模糊)
1. 判断是否开启自动排序:bool isSortingEnabled () const
函数原型:
bool QListWidget::isSortingEnabled() const;
逐词逐句底层解析:
bool:返回值类型,返回true或false;QListWidget:::成员函数;isSortingEnabled():函数名,"是不是开启了自动排序" 的意思;const:常成员函数。
返回值说明:
true表示开启自动排序;false表示不排序(默认)。
2. 设置是否开启自动排序:void setSortingEnabled (bool enable)
函数原型:
void QListWidget::setSortingEnabled(bool enable);
逐词逐句底层解析:
void:无返回值;QListWidget:::成员函数;setSortingEnabled():函数名,"设置是否开启自动排序" 的意思;bool enable:入参,enable是true开启,false关闭。
参数说明:
enable:true开启自动排序,false关闭。
3. 【重要】手动触发排序:void sortItems (Qt::SortOrder order = Qt::AscendingOrder)
函数原型:
void QListWidget::sortItems(Qt::SortOrder order = Qt::AscendingOrder);
逐词逐句底层解析:
void:无返回值;QListWidget:::成员函数;sortItems():函数名,"排序条目" 的意思;Qt::SortOrder order:入参,排序顺序,默认是升序;Qt::SortOrder是枚举类型,有两个值:Qt::AscendingOrder:升序(默认);Qt::DescendingOrder:降序。
参数说明:
order:排序顺序,Qt::AscendingOrder升序,Qt::DescendingOrder降序;- 默认是升序。
关键注意事项:
sortItems()可独立使用,无需依赖sortingEnabled状态 ------ 哪怕sortingEnabled=false,调用sortItems()也会立即排序!
4.1.3 使用示例
#include <Qt>
// 先关闭自动排序(批量添加时推荐)
ui->listWidget->setSortingEnabled(false);
// 批量添加条目(乱序添加)
ui->listWidget->addItem("Python");
ui->listWidget->addItem("C++");
ui->listWidget->addItem("Java");
ui->listWidget->addItem("Go");
// 示例1:开启自动排序(按文本升序排列)
ui->listWidget->setSortingEnabled(true);
// 此时条目会自动排序:C++ → Go → Java → Python
// 示例2:手动触发降序排序(无需开启 sortingEnabled)
ui->listWidget->sortItems(Qt::DescendingOrder);
// 此时条目会降序排列:Python → Java → Go → C++
4.1.4 关键注意事项(必知!)
- 排序规则(超级重要!):默认按 Unicode 编码升序,数字 < 字母 < 中文;
- 行号变化(超级重要!):排序后原行号失效,重新分配;
- 性能影响(超级重要!):大量条目批量增删时建议先关闭自动排序;
- 手动排序(超级重要!) :
sortItems()可独立使用,无需开启sortingEnabled; - 默认值为 false。
4.2 属性七:isWrapping------ 条目要不要换行显示?
4.2.1 属性的核心定义
isWrapping 是 QListWidget 用于控制列表条目在控件宽度不足时是否自动换行 的属性 ------ 默认值为 false(不换行,仅纵向单列展示);设为 true 时,条目从左到右排列,一行放不下则换行,形成多列流式布局。
通俗理解:isWrapping 就像 "清单的换行开关"------ 如果开关关闭,所有条目排成一列,从上到下;如果开关打开,条目先从左到右排,一行排不下了就换到下一行,形成多列,像网格一样。
这里有几个超级重要的规则,必须牢记:
- 默认值为 false(不换行,纵向单列)------ 刚创建 QListWidget 时,条目是纵向单列排列的;
- 设为 true 时变为多列流式布局 :
- 条目从左到右排列,一行放不下则换行;
- 布局依赖列表视图模式(默认是
IconMode,适合换行;如果是ListMode,换行效果可能不同);
- 行号计算(超级重要!) :
count()仍统计总条目数,不受换行影响;currentRow()按视觉行号计算(而非原始添加顺序);
- spacing 同时控制水平和垂直间距(超级重要!) :
- 开启换行后,
spacing属性同时控制条目间的水平间距 (左右)和垂直间距(上下);
- 开启换行后,
- 视觉适配(超级重要!) :
- 换行适合展示短文本、小图标类条目;
- 长文本条目换行后可读性降低,不建议用换行布局;
- 需配合固定宽度触发换行 :
- 你需要给 QListWidget 设置一个固定宽度,当一行放不下所有条目时才会触发换行;
- 如果 QListWidget 宽度自适应,可能会一直变宽,不会换行。
4.2.2 关联 API 详解(逐词逐句,零模糊)
1. 判断是否允许换行:bool isWrapping () const
函数原型:
bool QListWidget::isWrapping() const;
逐词逐句底层解析:
bool:返回值类型,返回true或false;QListWidget:::成员函数;isWrapping():函数名,"是不是允许换行" 的意思;const:常成员函数。
返回值说明:
true表示允许换行;false表示不换行(默认)。
2. 设置是否允许换行:void setWrapping (bool wrap)
函数原型:
void QListWidget::setWrapping(bool wrap);
逐词逐句底层解析:
void:无返回值;QListWidget:::成员函数;setWrapping():函数名,"设置是否允许换行" 的意思;bool wrap:入参,wrap是true允许换行,false不换行。
参数说明:
wrap:true允许换行,false不换行。
4.2.3 使用示例
// 先给 QListWidget 设置固定宽度(触发换行!)
ui->listWidget->setFixedWidth(300);
// 开启换行
ui->listWidget->setWrapping(true);
// 设置条目间距(同时控制水平和垂直!)
ui->listWidget->setSpacing(10);
// 添加多个短文本条目
for (int i = 1; i <= 20; ++i) {
ui->listWidget->addItem(QString("条目%1").arg(i));
}
// 此时条目会从左到右排列,一行放不下则换行,形成多列流式布局
4.2.4 关键注意事项(必知!)
- 设为 true 时变为多列流式布局(超级重要!);
- spacing 同时控制水平和垂直间距(超级重要!);
- 需配合固定宽度触发换行(超级重要!);
- 视觉适配:适合短文本、小图标条目;
- 默认值为 false。
示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//OK,本文件我们来学习QListWidget的剩下几个属性,也是比较简单的,一般使用默认的就行~~~
//sortingEnabled、isWrapping、selectRectVisible属性,具体的看下面解析
/**
* @class QListWidget
* @brief Qt中纵向列表展示控件的排序/换行/选中视觉属性
* @details 以下属性聚焦QListWidget的功能开关与选中视觉定制,sortingEnabled控制列表自动排序,isWrapping控制条目换行布局,selectRectVisible控制选中条目的矩形高亮显隐,是定制列表交互与视觉风格的核心配置。
*/
// ============================== 核心属性详解 ==============================
/**
* @property QListWidget::sortingEnabled
* @brief QListWidget是否允许列表条目自动排序的属性
* @details 控制列表是否按条目文本内容自动升序排序,默认值为false(不排序);设为true时,新增/修改条目文本、插入条目都会触发自动排序,条目行号会重新分配。
*
* 【关联API详解】
* 1. bool isSortingEnabled() const → 判断是否开启自动排序;
* 2. void setSortingEnabled(bool enable) → 设置是否开启自动排序;
* 3. void sortItems(Qt::SortOrder order = Qt::AscendingOrder) → 手动触发排序(可指定升序/降序,无需开启sortingEnabled)。
*
* @使用示例:
* // 开启自动排序(按文本升序排列)
* ui->listWidget->setSortingEnabled(true);
* // 手动触发降序排序(即使未开启自动排序也生效)
* ui->listWidget->sortItems(Qt::DescendingOrder);
*
* 【关键注意事项】
* 1. 排序规则:默认按文本的Unicode编码升序排列(数字<字母<中文),中文按拼音/Unicode排序;
* 2. 行号变化:排序后原行号失效,条目行号重新分配,currentRow/count等属性仍正常生效;
* 3. 性能影响:大量条目(如1000+)开启自动排序会轻微影响增删效率,建议批量增删后再开启;
* 4. 手动排序:sortItems()可独立使用,无需依赖sortingEnabled状态。
*/
/**
* @property QListWidget::isWrapping
* @brief QListWidget是否允许条目换行显示的属性
* @details 控制列表条目在控件宽度不足时是否自动换行,默认值为false(不换行,仅纵向单列展示);设为true时,条目从左到右排列,一行放不下则换行,形成多列流式布局。
*
* 【关联API详解】
* 1. bool isWrapping() const → 判断是否允许换行;
* 2. void setWrapping(bool wrap) → 设置是否允许换行。
*
* @使用示例:
* // 开启换行,固定列表宽度触发流式布局
* ui->listWidget->setWrapping(true);
* ui->listWidget->setFixedWidth(200); // 宽度不足时条目自动换行
*
* 【关键注意事项】
* 1. 布局依赖:换行效果需配合列表视图模式(默认IconMode),纵向列表开启后变为流式多列布局;
* 2. 行号计算:count()仍统计总条目数,currentRow按视觉行号计算(而非原始添加顺序);
* 3. 间距配合:换行后spacing属性同时控制条目间的水平和垂直间距,可通过setSpacing()调整;
* 4. 视觉适配:换行适合展示短文本、小图标类条目,长文本条目换行后可读性降低。
*/
/**
* @property QListWidget::selectRectVisible
* @brief QListWidget选中条目对应的高亮矩形框是否可见的属性
* @details 控制选中条目周围是否显示系统默认的高亮矩形框,默认值为true(可见);设为false时,选中状态仍生效(触发选中信号),但视觉上无矩形框高亮,可通过QSS自定义选中样式替代。
*
* 【关联API详解】
* 1. bool isSelectRectVisible() const → 判断选中矩形框是否可见;
* 2. void setSelectRectVisible(bool visible) → 设置选中矩形框显隐。
*
* @使用示例:
* // 隐藏默认选中矩形框,自定义选中条目背景色
* ui->listWidget->setSelectRectVisible(false);
* // 给选中条目设置红色背景(需结合QSS或条目属性)
* QListWidgetItem* item = ui->listWidget->currentItem();
* if (item) item->setBackground(Qt::lightGray);
*
* 【关键注意事项】
* 1. 仅视觉影响:隐藏矩形框不改变选中逻辑、行号/条目对象关联,也不影响选中信号触发;
* 2. 样式覆盖:若通过QSS设置了`QListWidget::item:selected`样式,该属性可能被覆盖,以QSS样式为准;
* 3. 交互兼容:即使隐藏矩形框,条目仍可被点击/选中/双击,所有交互功能正常。
*/
//比较简单,所以我就不演示了
}
Widget::~Widget()
{
delete ui;
}
第五章 QListWidget 核心方法详解
讲完了所有核心属性,我们接下来讲 QListWidget 的核心方法 ------ 这是操作列表条目最核心的接口,覆盖添加、插入、删除、选中、查询全生命周期。我们讲:addItem(两种重载)、currentItem、setCurrentItem、setCurrentRow、insertItem(两种重载)、item、takeItem。
5.1 方法一:addItem ()------ 向列表末尾添加条目(两种重载)
5.1.1 方法的核心定义
addItem() 是 QListWidget 最基础、最常用、最高频 的方法 ------ 它用于向列表末尾添加条目,有两种重载形式:
- 重载 1:通过文本快速创建默认样式条目;
- 重载 2:添加自定义配置(图标 / 字体 / 尺寸)的条目。
通俗理解:addItem() 就像 "在清单的最后面加一行纸"------ 重载 1 是 "直接拿一张空白纸,写上字加进去";重载 2 是 "拿一张你已经写好字、贴好图、设置好字体的纸加进去"。
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 内存管理!(超级重要!说三遍!) :
- 重载 2 的
item参数(自定义条目指针)无需手动delete------ 列表接管所有权,条目会随 QListWidget 一起销毁; - 删除条目需用
takeItem(),不要直接delete列表里的条目!
- 重载 2 的
- 排序影响(超级重要!) :
- 若开启
sortingEnabled=true,添加的条目会自动排序,不一定在列表末尾! - 排序后条目位置由文本决定,不是添加顺序!
- 若开启
- 空值处理 :
- 重载 1 的
label为空字符串也可添加,显示为空行; - 重载 2 的
item为nullptr时无操作,不会添加任何东西;
- 重载 1 的
- 开篇的注意事项再强调一遍!(超级重要!) :
- 重载 2 的
item必须是new出来的堆对象,不能是栈上的对象! - 否则代码结束后局部对象被销毁,界面上看不到条目!
- 重载 2 的
5.1.2 关联 API 详解(逐词逐句,零模糊)
addItem() 有两种重载形式,我们逐个来讲:
1. 重载 1:通过文本快速添加条目
函数原型:
void QListWidget::addItem(const QString &label);
逐词逐句底层解析:
void:无返回值;QListWidget:::成员函数;addItem():函数名,"添加条目" 的意思;const QString &label:入参,label是条目显示的文本。
参数说明:
label:条目显示的文本,QString类型;- 可以是空字符串(显示为空行)。
特点:
- 快速、便捷,无需手动
newQListWidgetItem; - 条目是默认样式,无图标、默认字体。
2. 重载 2:添加自定义配置的条目
函数原型:
void QListWidget::addItem(QListWidgetItem *item);
逐词逐句底层解析:
void:无返回值;QListWidget:::成员函数;addItem():函数名,"添加条目" 的意思;QListWidgetItem *item:入参,item是自定义的 QListWidgetItem 对象指针。
参数说明:
item:自定义的 QListWidgetItem 对象指针;- 必须是
new出来的堆对象!不能是栈对象! - 不能是
nullptr(否则无操作)。
特点:
- 灵活,可自定义图标、字体、尺寸、对齐方式等;
- 列表接管所有权,无需手动
delete。
5.1.3 使用示例
#include <QListWidgetItem>
#include <QIcon>
// 示例1:重载 1------快速添加文本条目(最常用!)
ui->listWidget->addItem("C++");
ui->listWidget->addItem("Java");
ui->listWidget->addItem("Python");
// 示例2:重载 2------添加自定义图标+字体的条目
// 1. new 一个堆对象(必须!)
QListWidgetItem* customItem = new QListWidgetItem("自定义条目");
// 2. 自定义配置
customItem->setIcon(QIcon(":/images/icon.png")); // 设置图标
QFont font("微软雅黑", 12, QFont::Bold);
customItem->setFont(font); // 设置字体
// 3. 添加到列表
ui->listWidget->addItem(customItem);
// 注意:不需要手动 delete customItem!列表接管了!
5.1.4 关键注意事项(必知!)
- 内存管理!(超级重要!说三遍!):重载 2 的 item 无需手动 delete,列表接管所有权;
- 必须是 new 出来的堆对象!(超级重要!开篇就讲!):重载 2 的 item 不能是栈对象!
- 排序影响(超级重要!):开启 sortingEnabled 后,添加的条目会自动排序,不一定在末尾!
- 空值处理:重载 2 的 item 为 nullptr 时无操作。
5.2 方法二:currentItem ()------ 获取当前选中的条目对象
5.2.1 方法的核心定义
currentItem() 是 QListWidget 用于获取当前选中条目对象指针 的核心方法 ------ 无选中条目 / 列表为空时返回 nullptr,是操作选中条目属性(文本 / 图标)的核心入口。
通俗理解:currentItem() 就像 "拿到清单上当前被标亮的那一行纸"------ 拿到这张纸后,你就可以读它上面的字、改它上面的字、换它的图标;如果没有任何一行被标亮,或者清单是空的,你就拿不到纸(返回 nullptr)。
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 判空强制!(超级重要!说三遍!) :
- 列表为空 / 无选中时返回
nullptr; - 必须先判空再操作! 直接操作
nullptr会导致程序崩溃! - 这是新手最容易踩的坑之一!
- 列表为空 / 无选中时返回
- 联动 currentRow :
currentItem()对应的行号就是currentRow(),二者一一对应; - 修改其中一个,另一个自动更新 :修改
currentItem会自动更新currentRow,反之亦然。
5.2.2 关联 API 详解(逐词逐句,零模糊)
1. 获取当前选中条目对象:QListWidgetItem* currentItem () const
函数原型:
QListWidgetItem* QListWidget::currentItem() const;
逐词逐句底层解析:
QListWidgetItem*:返回值类型,返回当前选中条目的指针;QListWidget:::成员函数;currentItem():函数名,"获取当前条目" 的意思;const:常成员函数。
返回值说明:
- 返回
QListWidgetItem*类型的指针; - 有选中时返回对应条目的指针;
- 无选中 / 列表为空时返回
nullptr; - 必须先判空再操作!
5.2.3 使用示例
#include <QListWidgetItem>
#include <QDebug>
// 添加条目并选中第一个
ui->listWidget->addItem("条目1");
ui->listWidget->setCurrentRow(0);
// 获取当前选中条目并操作(必须先判空!)
QListWidgetItem* selectedItem = ui->listWidget->currentItem();
if (selectedItem != nullptr) { // 判空!判空!判空!
// 读取文本
qDebug() << "当前选中条目文本:" << selectedItem->text();
// 修改文本
selectedItem->setText("已修改的条目");
} else {
qDebug() << "当前无选中项";
}
5.2.4 关键注意事项(必知!)
- 判空强制!(超级重要!说三遍!):必须先判空再操作,否则程序崩溃!
- 联动 currentRow:二者一一对应;
- 无选中返回 nullptr。
5.3 方法三:setCurrentItem ()------ 设置指定条目为当前选中项
5.3.1 方法的核心定义
setCurrentItem() 是 QListWidget 用于精准选中指定条目 的方法 ------item 需是当前列表内的条目,设置后触发 currentItemChanged/currentRowChanged 信号。
通俗理解:setCurrentItem() 就像 "指定清单上的某一行纸,把它标亮"------ 你要指定的这一行纸必须已经在清单里了,否则标亮不了。
这里有几个超级重要的规则,必须牢记:
- 有效性(超级重要!) :
item必须是已添加到列表的条目;- 如果
item是刚new出来还没添加的,或者是其他列表的条目,设置无效;
- 信号触发(超级重要!) :
- 设置有效条目会依次触发
currentItemChanged、currentRowChanged信号;
- 设置有效条目会依次触发
- 取消选中(超级重要!) :
- 传入
nullptr可清空所有选中状态,currentRow()变为 -1;
- 传入
- 等价操作 :
setCurrentItem(item)等价于setCurrentRow(row_of_item)。
5.3.2 关联 API 详解(逐词逐句,零模糊)
1. 设置指定条目为当前选中项:void setCurrentItem (QListWidgetItem* item)
函数原型:
void QListWidget::setCurrentItem(QListWidgetItem* item);
逐词逐句底层解析:
void:无返回值;QListWidget:::成员函数;setCurrentItem():函数名,"设置当前条目" 的意思;QListWidgetItem* item:入参,要选中的条目指针。
参数说明:
item:要选中的条目指针;- 必须是已添加到列表的条目;
- 传入
nullptr可取消所有选中。
5.3.3 使用示例
#include <QListWidgetItem>
// 添加几个条目并保存指针
QListWidgetItem* item1 = new QListWidgetItem("条目1");
QListWidgetItem* item2 = new QListWidgetItem("条目2");
ui->listWidget->addItem(item1);
ui->listWidget->addItem(item2);
// 示例1:选中 item2
ui->listWidget->setCurrentItem(item2);
// 示例2:取消所有选中
ui->listWidget->setCurrentItem(nullptr);
5.3.4 关键注意事项(必知!)
- 有效性(超级重要!):item 必须是已添加到列表的条目;
- 信号触发(超级重要!):设置有效条目会触发信号;
- 传入 nullptr 取消选中;
- 等价于 setCurrentRow。
5.4 方法四:setCurrentRow ()------ 通过行号设置当前选中项
这个方法我们在讲 currentRow 属性时已经详细讲过了,这里简单回顾一下:
- 行号从 0 开始;
- 超出范围取消选中;
- 设置有效行号触发
currentRowChanged和currentItemChanged信号。
5.5 方法五:insertItem ()------ 在指定位置插入条目(两种重载)
5.5.1 方法的核心定义
insertItem() 是 QListWidget 用于在指定行号位置插入条目 的方法 ------ 区别于 addItem()(仅追加末尾),它支持在任意位置插入,有两种重载形式:
- 重载 1:通过文本快速插入默认样式条目;
- 重载 2:插入自定义配置的条目。
通俗理解:insertItem() 就像 "在清单的指定位置插一行纸"------ 比如在第 2 行(行号 1)前面插一行,原来的第 2 行及后面的行都会自动往后挪一位。
这里有几个超级重要的规则,必须牢记:
- 行号容错(超级重要!) :
row < 0→ 插在开头(行号 0);row > count()→ 插在末尾(等价于addItem());- 不用担心行号超出范围,Qt 会自动适配!
- 行号偏移(超级重要!) :
- 插入位置后的条目行号自动 +1;
- 比如在索引 1 插入,原索引 1 的条目变为索引 2,原索引 2 变为索引 3,以此类推;
- 内存管理(超级重要!) :
- 重载 2 的
item必须是new出来的堆对象; - 列表接管所有权,无需手动
delete;
- 重载 2 的
- 排序影响(超级重要!) :
- 若开启
sortingEnabled=true,插入的条目会自动排序,不一定在你指定的位置!
- 若开启
5.5.2 关联 API 详解(逐词逐句,零模糊)
1. 重载 1:通过文本快速插入条目
函数原型:
void QListWidget::insertItem(int row, const QString &label);
逐词逐句底层解析:
void:无返回值;QListWidget:::成员函数;insertItem():函数名,"插入条目" 的意思;int row:入参,插入位置的行号;const QString &label:入参,条目显示的文本。
参数说明:
row:插入位置的行号,从 0 开始;row < 0→ 插开头;row > count()→ 插末尾;
label:条目显示的文本。
2. 重载 2:插入自定义配置的条目
函数原型:
void QListWidget::insertItem(int row, QListWidgetItem *item);
逐词逐句底层解析:
void:无返回值;QListWidget:::成员函数;insertItem():函数名,"插入条目" 的意思;int row:入参,插入位置的行号;QListWidgetItem *item:入参,自定义的条目指针。
参数说明:
row:插入位置的行号;item:自定义的条目指针;- 必须是
new出来的堆对象! - 不能是
nullptr。
- 必须是
5.5.3 使用示例
#include <QListWidgetItem>
// 先添加几个条目
ui->listWidget->addItem("条目1"); // 行号 0
ui->listWidget->addItem("条目3"); // 行号 1
// 示例1:重载 1------在第 2 行(行号 1)前面插入"条目2"
ui->listWidget->insertItem(1, "条目2");
// 此时列表顺序:条目1(0)→ 条目2(1)→ 条目3(2)
// 示例2:重载 2------在开头插入自定义条目
QListWidgetItem* customItem = new QListWidgetItem("自定义插入条目");
ui->listWidget->insertItem(0, customItem); // row=0 插开头
// 此时列表顺序:自定义插入条目(0)→ 条目1(1)→ 条目2(2)→ 条目3(3)
5.5.4 关键注意事项(必知!)
- 行号容错(超级重要!):row<0 插开头,row>count () 插末尾;
- 行号偏移(超级重要!):插入位置后的条目行号自动 +1;
- 内存管理(超级重要!):重载 2 的 item 必须是 new 出来的堆对象;
- 排序影响(超级重要!):开启 sortingEnabled 后,插入的条目会自动排序。
5.6 方法六:item ()------ 通过行号获取对应条目对象
5.6.1 方法的核心定义
item() 是 QListWidget 用于通过行号获取对应条目对象指针 的方法 ------ 行号超出范围时返回 nullptr,是遍历 / 修改指定行条目的核心方法。
通俗理解:item() 就像 "拿到清单上指定行号的那一行纸"------ 比如你要拿第 2 行(行号 1)的纸,就调用 item(1);如果行号不对,就拿不到(返回 nullptr)。
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 判空必须!(超级重要!) :
- 行号无效(
row < 0或row >= count())时返回nullptr; - 必须先判空再操作! 直接操作会崩溃!
- 行号无效(
- 实时性(超级重要!) :
- 行号随增删 / 排序动态变化;
- 如果你保存了某个行号,过了一段时间(比如增删了条目、排序了),这个行号对应的条目可能变了!
- 遍历常用 :遍历列表时常用
for(int i=0; i<count(); i++)配合item(i)。
5.6.2 关联 API 详解(逐词逐句,零模糊)
1. 通过行号获取对应条目对象:QListWidgetItem* item (int row) const
函数原型:
QListWidgetItem* QListWidget::item(int row) const;
逐词逐句底层解析:
QListWidgetItem*:返回值类型,返回条目指针;QListWidget:::成员函数;item():函数名,"获取条目" 的意思;int row:入参,行号。
参数说明:
row:行号,从 0 开始;- 有效范围:
0 ≤ row < count()。
返回值说明:
- 返回
QListWidgetItem*类型的指针; - 行号有效返回对应条目指针;
- 行号无效返回
nullptr; - 必须先判空再操作!
5.6.3 使用示例
#include <QListWidgetItem>
#include <QDebug>
// 添加几个条目
ui->listWidget->addItem("条目1");
ui->listWidget->addItem("条目2");
ui->listWidget->addItem("条目3");
// 示例1:获取第 2 行(行号 1)的条目并操作(必须判空!)
QListWidgetItem* item = ui->listWidget->item(1);
if (item != nullptr) { // 判空!
qDebug() << "第 2 行的文本:" << item->text();
item->setText("已修改的条目2");
}
// 示例2:遍历所有条目(常用!)
for (int i = 0; i < ui->listWidget->count(); ++i) {
QListWidgetItem* loopItem = ui->listWidget->item(i);
if (loopItem != nullptr) { // 判空!
qDebug() << "第" << i+1 << "行:" << loopItem->text();
}
}
5.6.4 关键注意事项(必知!)
- 判空必须!(超级重要!):行号无效返回 nullptr,必须先判空再操作!
- 实时性(超级重要!):行号随增删 / 排序动态变化;
- 遍历常用:配合 for 循环遍历所有条目。
5.7 方法七:takeItem ()------ 删除指定行的条目,并返回被删除的条目
5.7.1 方法的核心定义
takeItem() 是 QListWidget 用于删除指定行号条目 的核心方法 ------ 注意!它仅将条目从列表中移除,不自动释放内存 ,需手动 delete 返回的指针避免内存泄漏!
通俗理解:takeItem() 就像 "把清单上指定行的那一行纸抽出来"------ 抽出来后,这张纸就不在清单里了,其他行会自动往前挪填补位置;但这张纸还在你手里,你要自己处理掉(delete),否则它会一直占着内存(内存泄漏)!
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 内存管理!(超级重要!说三遍!) :
takeItem()仅将条目从列表中移除,不自动释放内存!- 必须手动
delete返回的指针! 否则会内存泄漏! - 这是新手最容易踩的坑之一!
- 行号偏移(超级重要!) :
- 删除后后续条目行号自动 -1;
- 比如删除索引 1,原索引 2 的条目变为索引 1,原索引 3 变为索引 2,以此类推;
- 选中状态(超级重要!) :
- 若删除的是选中条目,
currentRow()变为 -1,取消选中;
- 若删除的是选中条目,
- 返回值(超级重要!) :
- 返回被删除的条目指针;
- 行号无效返回
nullptr; - 拿到返回的指针后,要么
delete它,要么把它添加到其他列表,不要让它泄漏!
5.7.2 关联 API 详解(逐词逐句,零模糊)
1. 删除指定行的条目:QListWidgetItem* takeItem (int row)
函数原型:
QListWidgetItem* QListWidget::takeItem(int row);
逐词逐句底层解析:
QListWidgetItem*:返回值类型,返回被删除的条目指针;QListWidget:::成员函数;takeItem():函数名,"拿走条目" 的意思;int row:入参,要删除的行号。
参数说明:
row:要删除的行号,从 0 开始;- 有效范围:
0 ≤ row < count()。
返回值说明:
- 返回
QListWidgetItem*类型的指针; - 行号有效返回被删除的条目指针;
- 行号无效返回
nullptr; - 必须手动 delete 返回的指针!
5.7.3 使用示例
#include <QListWidgetItem>
#include <QDebug>
// 添加几个条目
ui->listWidget->addItem("条目1"); // 行号 0
ui->listWidget->addItem("条目2"); // 行号 1
ui->listWidget->addItem("条目3"); // 行号 2
// 示例:删除第 2 行(行号 1)的条目,并释放内存(必须!)
QListWidgetItem* deletedItem = ui->listWidget->takeItem(1);
if (deletedItem != nullptr) { // 判空
qDebug() << "被删除的条目文本:" << deletedItem->text();
delete deletedItem; // 必须手动 delete!否则内存泄漏!
deletedItem = nullptr; // 置空,避免野指针
}
// 此时列表顺序:条目1(0)→ 条目3(1),条目2 已被删除并释放
5.7.4 关键注意事项(必知!)
- 内存管理!(超级重要!说三遍!):必须手动 delete 返回的指针!否则内存泄漏!
- 行号偏移(超级重要!):删除后后续条目行号自动 -1;
- 选中状态(超级重要!):删除选中条目会取消选中;
- 返回值判空:行号无效返回 nullptr。
示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//OK,那么本文件我们就来学习一下QListWidget的核心方法,但是其实也是比较简单的
//最关键的也就是addItem方法,剩下的倒是都没什么
//还有一个currentItem也还行,获取到用户选择的条目~~~
//还有一个删除指定位置条目的方法,名字是takeItem,也得稍微注意一下~~~
/**
* @class QListWidget
* @brief Qt中纵向列表展示控件的核心条目操作方法
* @details 以下方法覆盖QListWidget条目全生命周期管理(添加/插入/删除/选中/查询),是操作列表条目最核心的接口,支持通过文本快速创建条目、精准选中/查询指定行条目、灵活增删条目,适配各类列表交互场景。
*/
// ============================== 核心方法详解 ==============================
/**
* @fn void QListWidget::addItem(const QString& label)
* @fn void QListWidget::addItem(QListWidgetItem *item)
* @brief 向列表**末尾**添加条目(两种重载形式)
* @details 基础条目添加接口,重载1通过文本快速创建默认样式条目,重载2添加自定义配置(图标/字体/尺寸)的条目,添加后条目所有权移交至列表。
*
* @参数说明:
* @param label - 重载1参数,条目显示的文本内容(空字符串也可添加,显示为空行);
* @param item - 重载2参数,自定义的QListWidgetItem对象指针(不可为nullptr)。
*
* @使用示例:
* // 重载1:快速添加文本条目
* ui->listWidget->addItem("基础文本条目");
*
* // 重载2:添加自定义图标+字体的条目
* QListWidgetItem* customItem = new QListWidgetItem("自定义条目");
* customItem->setIcon(QIcon(":/icon.png"));
* customItem->setFont(QFont("微软雅黑", 12));
* ui->listWidget->addItem(customItem);
*
* 【关键注意事项】
* 1. 内存管理:重载2的item无需手动delete(列表接管所有权),删除条目需用takeItem;
* 2. 排序影响:若开启sortingEnabled=true,添加的条目会自动排序,不一定在列表末尾;
* 3. 空值处理:item为nullptr时重载2无操作,label为空时重载1添加空行条目。
*/
/**
* @fn QListWidgetItem* QListWidget::currentItem() const
* @brief 获取当前**选中**的条目对象指针
* @details 核心查询接口,返回当前激活选中的条目指针,无选中条目/列表为空时返回nullptr,是操作选中条目属性(文本/图标)的核心入口。
*
* @返回值:QListWidgetItem* - 当前选中条目指针(无选中返回nullptr)。
*
* @使用示例:
* // 获取选中条目并修改其文本
* QListWidgetItem* selectedItem = ui->listWidget->currentItem();
* if (selectedItem != nullptr) { // 必须判空,避免空指针崩溃
* selectedItem->setText("已选中:" + selectedItem->text());
* }
*
* 【关键注意事项】
* 1. 判空强制:列表为空/无选中时返回nullptr,直接操作会导致程序崩溃;
* 2. 联动关系:currentItem()对应的行号 = currentRow(),二者一一对应。
*/
/**
* @fn void QListWidget::setCurrentItem(QListWidgetItem* item)
* @brief 设置指定条目为当前**选中**项
* @details 精准选中条目接口,item需是当前列表内的条目,设置后触发currentItemChanged/currentRowChanged信号。
*
* @参数说明:
* @param item - 要选中的条目指针(nullptr则取消所有选中)。
*
* @使用示例:
* // 选中列表中第一个条目
* QListWidgetItem* targetItem = ui->listWidget->item(0);
* if (targetItem) ui->listWidget->setCurrentItem(targetItem);
*
* 【关键注意事项】
* 1. 有效性:item必须是已添加到列表的条目,否则设置无效;
* 2. 信号触发:设置有效条目会依次触发currentItemChanged、currentRowChanged信号;
* 3. 取消选中:传入nullptr可清空所有选中状态,currentRow()变为-1。
*/
/**
* @fn void QListWidget::setCurrentRow(int row)
* @brief 通过**行号**设置当前选中项
* @details 行号版选中接口,等价于setCurrentItem(item(row)),行号从0开始计数,超出有效范围则取消选中。
*
* @参数说明:
* @param row - 要选中的行号(有效范围:0 ≤ row < count())。
*
* @使用示例:
* // 选中第2行(索引1)的条目
* ui->listWidget->setCurrentRow(1);
*
* 【关键注意事项】
* 1. 行号规则:行号从0开始,count()为总行数,超出范围则取消选中;
* 2. 等价操作:setCurrentRow(row) ≡ setCurrentItem(item(row));
* 3. 信号触发:设置有效行号会触发currentRowChanged/currentItemChanged信号。
*/
/**
* @fn void QListWidget::insertItem(int row, const QString& label)
* @fn void QListWidget::insertItem(int row, QListWidgetItem *item)
* @brief 在指定**行号位置**插入条目(两种重载形式)
* @details 区别于addItem(仅追加末尾),支持在任意位置插入条目,行号超出范围时自动适配(<0插开头,>count()插末尾)。
*
* @参数说明:
* @param row - 插入位置的行号(从0开始);
* @param label - 重载1参数,条目显示文本;
* @param item - 重载2参数,自定义条目指针(不可为nullptr)。
*
* @使用示例:
* // 重载1:在第1行(索引0)插入文本条目
* ui->listWidget->insertItem(0, "插入到开头的条目");
*
* // 重载2:在第3行(索引2)插入自定义条目
* QListWidgetItem* insertItem = new QListWidgetItem("插入条目");
* insertItem->setForeground(Qt::blue); // 设置文本颜色
* ui->listWidget->insertItem(2, insertItem);
*
* 【关键注意事项】
* 1. 行号容错:row<0 → 插开头;row>count() → 插末尾;
* 2. 行号偏移:插入位置后的条目行号自动+1(如索引1插入,原索引1条目变为索引2);
* 3. 内存管理:重载2的item所有权移交列表,无需手动delete。
*/
/**
* @fn QListWidgetItem* QListWidget::item(int row) const
* @brief 通过**行号**获取对应条目指针
* @details 行号→条目映射接口,返回指定行的条目指针,行号超出范围时返回nullptr,是遍历/修改指定行条目的核心方法。
*
* @参数说明:
* @param row - 要查询的行号(从0开始)。
*
* @返回值:QListWidgetItem* - 指定行条目指针(行号无效返回nullptr)。
*
* @使用示例:
* // 遍历所有条目并打印文本
* for (int i = 0; i < ui->listWidget->count(); ++i) {
* QListWidgetItem* item = ui->listWidget->item(i);
* if (item) qDebug() << "第" << i+1 << "行:" << item->text();
* }
*
* 【关键注意事项】
* 1. 判空必须:行号无效时返回nullptr,直接操作会崩溃;
* 2. 实时性:行号随增删/排序动态变化,需注意操作时机。
*/
/**
* @fn QListWidgetItem* QListWidget::takeItem(int row)
* @brief 删除指定**行号**的条目,并返回被删除的条目指针
* @details 核心删除接口,仅将条目从列表中移除(不自动释放内存),需手动delete返回的指针避免内存泄漏。
*
* @参数说明:
* @param row - 要删除的行号(从0开始)。
*
* @返回值:QListWidgetItem* - 被删除的条目指针(行号无效返回nullptr)。
*
* @使用示例:
* // 删除第1行(索引0)的条目并释放内存
* QListWidgetItem* deletedItem = ui->listWidget->takeItem(0);
* if (deletedItem) {
* delete deletedItem; // 必须手动释放,否则内存泄漏
* deletedItem = nullptr;
* }
*
* 【关键注意事项】
* 1. 内存管理:takeItem仅移除条目,需手动delete返回指针;
* 2. 行号偏移:删除后后续条目行号自动-1;
* 3. 选中状态:若删除的是选中条目,currentRow()变为-1,取消选中。
*/
}
Widget::~Widget()
{
delete ui;
}
第六章 QListWidget 核心交互信号详解
讲完了所有核心方法,我们最后来讲 QListWidget 的核心交互信号 ------ 这是列表与业务逻辑联动的核心桥梁,覆盖选中变更、点击、双击、鼠标悬浮等场景。按照你提供的顺序,我们讲:currentItemChanged、currentRowChanged、itemClicked、itemDoubleClicked、itemEntered,还会补充你资料里提到的 itemPressed、itemSelectionChanged、currentTextChanged。
6.1 信号一:currentItemChanged------ 选中不同条目时触发(条目对象版)
6.1.1 信号的核心定义
currentItemChanged 是 QListWidget 最核心、最常用 的选中变更信号 ------ 它在选中不同条目时触发(选中同一条目不触发),可同时获取 "当前选中条目" 和 "上一个选中条目",便于对比处理选中状态的变更逻辑。
通俗理解:currentItemChanged 就像 "清单上标亮的行变了时通知你"------ 它会告诉你 "之前标亮的是哪一行,现在标亮的是哪一行";如果你重复点击同一行,它不会通知你,因为标亮的行没变。
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 判空强制!(超级重要!说三遍!) :
current(当前选中条目)和old(上一个选中条目)都可能为nullptr!- 首次选中时,
old是nullptr; - 取消选中时,
current是nullptr; - 必须先判空再操作! 直接操作会崩溃!
- 触发规则(超级重要!) :
- 仅选中不同条目时触发;
- 重复点击同一条目不触发;
- 触发场景(超级重要!) :
- 用户点击不同条目;
- 代码调用
setCurrentItem()/setCurrentRow(); - 删除选中条目;
- 信号联动(超级重要!) :
- 与
currentRowChanged()同步触发; - 先触发
currentItemChanged,再触发currentRowChanged;
- 与
- 代码触发 :调用
setCurrentItem()/setCurrentRow()也会触发此信号。
6.1.2 信号参数详解
信号原型:
void QListWidget::currentItemChanged(QListWidgetItem* current, QListWidgetItem* old);
参数说明:
current:QListWidgetItem*类型,当前选中的条目指针;- 无选中时为
nullptr; - 必须先判空!
- 无选中时为
old:QListWidgetItem*类型,上一个选中的条目指针;- 首次选中时为
nullptr; - 必须先判空!
- 首次选中时为
6.1.3 使用示例
#include <QListWidgetItem>
#include <QDebug>
// 绑定信号(用 Lambda 表达式)
connect(ui->listWidget, &QListWidget::currentItemChanged,
this, [=](QListWidgetItem* cur, QListWidgetItem* prev){
// 判空!判空!判空!
QString prevText = prev ? prev->text() : "无";
QString curText = cur ? cur->text() : "无";
qDebug() << "选中项变更:" << prevText << " → " << curText;
// 典型用法:根据选中的条目更新右侧详情面板
if (cur != nullptr) {
// ui->detailLabel->setText(cur->text());
// ui->btnDelete->setEnabled(true);
} else {
// ui->detailLabel->setText("无选中项");
// ui->btnDelete->setEnabled(false);
}
});
6.1.4 关键注意事项(必知!)
- 判空强制!(超级重要!说三遍!):current 和 old 都可能为 nullptr,必须先判空!
- 仅选中不同条目时触发(超级重要!):重复点击同一条目不触发!
- 信号联动(超级重要!):与 currentRowChanged 同步触发!
- 代码也会触发。
6.2 信号二:currentRowChanged------ 选中不同条目时触发(行号版)
6.2.1 信号的核心定义
currentRowChanged 是 currentItemChanged 的简化版信号------ 它仅返回当前选中条目的行号,无需处理条目指针判空,适配仅需行号的场景(如行号统计、索引关联)。
通俗理解:currentRowChanged 就像 "清单上标亮的行变了时通知你行号"------ 它只告诉你 "现在标亮的是第几行(代码行号)",不告诉你之前是第几行;如果你只需要行号,用这个信号更轻量。
这里有几个超级重要的规则,必须牢记:
- 行号规则(超级重要!) :
- 行号从 0 开始;
- 无选中时参数为 -1;
- 用户视角需 +1 展示;
- 触发场景:所有导致选中项变更的操作均触发(点击 / 代码设置 / 删除选中项);
- 简洁性:仅需行号时优先使用此信号,无需处理条目指针。
6.2.2 信号参数详解
信号原型:
void QListWidget::currentRowChanged(int currentRow);
参数说明:
currentRow:int类型,当前选中条目的行号;- 从 0 开始;
- 无选中时为 -1。
6.2.3 使用示例
#include <QDebug>
// 绑定信号(用 Lambda 表达式)
connect(ui->listWidget, &QListWidget::currentRowChanged,
this, [=](int row){
if (row == -1) {
qDebug() << "当前无选中项";
ui->label->setText("当前无选中项");
} else {
qDebug() << "当前选中行号(代码):" << row;
ui->label->setText(QString("当前选中第%1行").arg(row + 1)); // 行号+1 适配用户
}
});
6.2.4 关键注意事项(必知!)
- 行号从 0 开始!(超级重要!);
- 无选中时为 -1;
- 简洁性:仅需行号时优先使用。
6.3 信号三:itemClicked------ 用户鼠标单击条目时触发
6.3.1 信号的核心定义
itemClicked 是 QListWidget 纯交互触发 的信号 ------ 它仅响应用户鼠标单击 操作,代码选中不触发,参数为被点击的条目指针(非 nullptr),是 "点击条目执行操作" 的核心入口。
通俗理解:itemClicked 就像 "用户用鼠标点了清单上某一行时通知你"------ 它只响应用户的点击,你用代码选中条目它不会通知你;而且点击的肯定是某一行,所以参数不会是 nullptr。
这里有几个超级重要的规则,必须牢记:
- 触发条件(超级重要!) :
- 仅用户单击触发;
- 代码调用
setCurrentItem()/setCurrentRow()不触发; - 这点和
currentItemChanged不一样!
- 参数有效性(超级重要!) :
item始终为有效条目指针(无需判空);- 点击列表空白处(无条目区域)不触发此信号;
- 选中联动(超级重要!) :
- 单击条目会自动将其设为选中项;
- 因此会先触发
itemClicked(),再触发currentItemChanged()/currentRowChanged();
- 重复点击同一条目也触发(超级重要!) :
- 这点和
currentItemChanged不一样! - 哪怕条目已经是选中项,再次点击也会触发
itemClicked()!
- 这点和
6.3.2 信号参数详解
信号原型:
void QListWidget::itemClicked(QListWidgetItem* item);
参数说明:
item:QListWidgetItem*类型,被单击的条目指针;- 始终有效(无需判空);
- 点击空白处不触发。
6.3.3 使用示例
#include <QListWidgetItem>
#include <QMessageBox>
// 绑定信号(用 Lambda 表达式)
connect(ui->listWidget, &QListWidget::itemClicked,
this, [=](QListWidgetItem* clickedItem){
// 无需判空!
QMessageBox::information(this, "点击提示",
QString("你点击了:%1").arg(clickedItem->text()));
});
6.3.4 关键注意事项(必知!)
- 仅用户单击触发(超级重要!):代码选中不触发!
- 参数有效性(超级重要!):无需判空!
- 选中联动(超级重要!):先触发 itemClicked,再触发 currentItemChanged!
- 重复点击同一条目也触发(超级重要!)!
6.4 信号四:itemDoubleClicked------ 用户鼠标双击条目时触发
6.4.1 信号的核心定义
itemDoubleClicked 是 QListWidget 适配 "双击条目执行核心操作" 场景的信号 ------ 它仅响应用户鼠标双击 操作,代码操作不触发,参数为被双击的条目指针(非 nullptr)。
通俗理解:itemDoubleClicked 就像 "用户用鼠标快速双击了清单上某一行时通知你"------ 它适合做 "打开文件""编辑条目""进入下一级" 这种需要双击确认的操作。
这里有几个超级重要的规则,必须牢记:
- 触发顺序(超级重要!) :
- 双击会先触发
itemClicked()(第一次单击),再触发此信号; - 如果你同时绑定了这两个信号,要注意逻辑冲突!
- 双击会先触发
- 触发条件(超级重要!) :
- 仅用户双击触发;
- 代码操作 / 单击均不触发;
- 参数有效性 :
item始终为有效条目指针(无需判空); - 交互场景:适合 "编辑 / 打开 / 查看详情" 等需要双击确认的操作。
6.4.2 信号参数详解
信号原型:
void QListWidget::itemDoubleClicked(QListWidgetItem* item);
参数说明:
item:QListWidgetItem*类型,被双击的条目指针;- 始终有效(无需判空)。
6.4.3 使用示例
#include <QListWidgetItem>
#include <QInputDialog>
// 绑定信号(用 Lambda 表达式)
connect(ui->listWidget, &QListWidget::itemDoubleClicked,
this, [=](QListWidgetItem* doubleItem){
// 双击条目编辑文本
QString newText = QInputDialog::getText(this, "编辑条目",
"修改文本:",
QLineEdit::Normal,
doubleItem->text());
if (!newText.isEmpty()) {
doubleItem->setText(newText);
}
});
6.4.4 关键注意事项(必知!)
- 触发顺序(超级重要!):先触发 itemClicked(第一次单击),再触发此信号!
- 仅用户双击触发;
- 参数有效性:无需判空。
6.5 信号五:itemEntered------ 鼠标光标进入条目区域时触发
6.5.1 信号的核心定义
itemEntered 是 QListWidget 用于鼠标悬浮交互 的信号 ------ 它在鼠标光标进入条目区域时触发,需开启鼠标跟踪才会触发!
通俗理解:itemEntered 就像 "鼠标移到清单上某一行时通知你"------ 你可以用它做 "鼠标悬浮高亮""显示 Tooltip 提示" 等效果;但注意,你必须先开启鼠标跟踪,否则它不会通知你!
这里有几个超级重要的规则,必须牢记,刻在脑子里:
- 前置条件!(超级重要!说三遍!) :
- 必须调用
setMouseTracking(true)! - 否则永不触发!
- 这是新手最容易忽略的!
- 必须调用
- 触发频率(超级重要!) :
- 鼠标在条目间移动时高频触发;
- 避免在信号槽内执行耗时操作!
- 仅进不出(超级重要!) :
- 此信号仅响应 "进入" 条目;
- 鼠标离开条目需结合
QMouseEvent手动处理(没有itemLeft信号);
- 参数有效性 :
item始终为有效条目指针(无需判空)。
6.5.2 信号参数详解
信号原型:
void QListWidget::itemEntered(QListWidgetItem* item);
参数说明:
item:QListWidgetItem*类型,鼠标进入的条目指针;- 始终有效(无需判空)。
6.5.3 使用示例
#include <QListWidgetItem>
// 第一步:必须开启鼠标跟踪!(超级重要!)
ui->listWidget->setMouseTracking(true);
// 第二步:绑定信号(用 Lambda 表达式)
connect(ui->listWidget, &QListWidget::itemEntered,
this, [=](QListWidgetItem* enterItem){
// 鼠标进入时设置浅灰背景
enterItem->setBackground(Qt::lightGray);
// 注意:鼠标离开时恢复背景需结合鼠标事件手动处理
});
6.5.4 关键注意事项(必知!)
- 前置条件!(超级重要!说三遍!):必须调用 setMouseTracking (true)!
- 触发频率(超级重要!):避免在信号槽内执行耗时操作!
- 仅进不出(超级重要!):离开需手动处理!
- 参数有效性:无需判空。
6.6 补充信号:itemPressed、itemSelectionChanged、currentTextChanged
我们简单补充一下:
6.6.1 itemPressed------ 鼠标按键在条目上按下时触发
- 触发时机:鼠标按键在条目上按下(尚未释放)时触发;
- 典型用法:自定义拖拽操作(Drag & Drop)的起始判断;
- 注意:此时还未产生 "点击" 或 "选中" 的最终结果。
6.6.2 itemSelectionChanged------ 选中状态改变时触发(多选模式专用!)
- 触发时机:列表中被选中的条目集合发生变化时触发;
- 关键点 :
- 单选模式下,行为类似
currentItemChanged; - 多选模式下最重要! ------
currentItemChanged只追踪 "当前焦点项",而这个信号追踪 "所有被选中的项";
- 单选模式下,行为类似
- 典型用法:批量操作按钮的状态更新(如选中多项时才启用 "批量删除")、统计选中数量。
6.6.3 currentTextChanged------ 当前选中项的文本改变时触发
- 触发时机:当前选中项变化导致显示的文本变化,或当前项被编辑后文本变化时触发;
- 典型用法:联动另一个只显示文本的标签、根据文本内容过滤其他列表。
示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QListWidgetItem>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//OK,本文件我们就来学习一下QListWidget的核心信号
//其实也没几个难的信号
/*
currentItemChanged(QListWidgetItem*current, QListWidgetItem* old)
选中不同元素时会触发. 参数是当前选中的元素和之前选中的元素.
currentRowChanged(int) 选中不同元素时会触发. 参数是当前选中元素的行数.
itemClicked(QListWidgetItem* item) 点击某个元素时触发
itemDoubleClicked(QListWidgetItem*item)双击某个元素时触发
itemEntered(QListWidgetItem* item) 鼠标进入元素时触发
*/
/**
* @class QListWidget
* @brief Qt中纵向列表展示控件的核心交互信号
* @details 以下信号覆盖QListWidget最核心的交互场景(选中变更、点击、双击、鼠标悬浮),是列表与业务逻辑联动的核心桥梁;不同信号适配不同交互需求,可精准响应用户操作并获取关键交互信息(选中条目/行号/点击对象)。
*/
// ============================== 核心信号详解 ==============================
/**
* @signal void QListWidget::currentItemChanged(QListWidgetItem* current, QListWidgetItem* old)
* @brief 选中**不同**条目时触发的信号(选中同一条目不触发)
* @details 核心选中变更信号,可同时获取"当前选中条目"和"上一个选中条目",便于对比处理选中状态的变更逻辑;触发场景包括用户点击不同条目、代码设置选中项、删除选中条目等。
*
* @参数说明:
* @param current - 当前选中的条目指针(无选中时为nullptr,如取消选中);
* @param old - 上一个选中的条目指针(无之前选中项时为nullptr,如首次选中)。
*
* @使用示例:
* // 绑定信号,打印选中条目变更记录
* connect(ui->listWidget, &QListWidget::currentItemChanged, this, [=](QListWidgetItem* cur, QListWidgetItem* prev){
* QString prevText = prev ? prev->text() : "无"; // 判空避免崩溃
* QString curText = cur ? cur->text() : "无";
* qDebug() << "选中项变更:" << prevText << " → " << curText;
* });
*
* 【关键注意事项】
* 1. 判空强制:current/old可能为nullptr(首次选中/取消选中),必须先判空再操作;
* 2. 触发规则:仅选中**不同**条目时触发(重复点击同一条目不触发);
* 3. 信号联动:与currentRowChanged()同步触发,先触发此信号,再触发currentRowChanged();
* 4. 代码触发:调用setCurrentItem/setCurrentRow也会触发此信号。
*/
/**
* @signal void QListWidget::currentRowChanged(int currentRow)
* @brief 选中**不同**条目时触发的信号(行号版)
* @details currentItemChanged()的简化版信号,仅返回当前选中条目的行号,无需处理条目指针判空,适配仅需行号的场景(如行号统计、索引关联)。
*
* @参数说明:
* @param currentRow - 当前选中条目的行号(从0开始计数;无选中时为-1)。
*
* @使用示例:
* // 绑定信号,更新UI显示选中行号
* connect(ui->listWidget, &QListWidget::currentRowChanged, this, [=](int row){
* if (row == -1) {
* ui->label->setText("当前无选中项");
* } else {
* ui->label->setText(QString("当前选中第%1行").arg(row + 1)); // 行号+1适配用户习惯
* }
* });
*
* 【关键注意事项】
* 1. 行号规则:行号从0开始,用户视角需+1展示;无选中时参数为-1;
* 2. 触发场景:所有导致选中项变更的操作均触发(点击/代码设置/删除选中项);
* 3. 简洁性:仅需行号时优先使用此信号,无需处理条目指针。
*/
/**
* @signal void QListWidget::itemClicked(QListWidgetItem* item)
* @brief **用户鼠标单击**列表条目时触发的信号(代码选中不触发)
* @details 纯交互触发信号,仅响应用户单击操作,参数为被点击的条目指针(非nullptr),是"点击条目执行操作"的核心入口。
*
* @参数说明:
* @param item - 被单击的条目指针(不会为nullptr,点击列表空白处不触发此信号)。
*
* @使用示例:
* // 绑定信号,单击条目弹出详情提示
* connect(ui->listWidget, &QListWidget::itemClicked, this, [=](QListWidgetItem* clickedItem){
* QMessageBox::information(this, "点击提示", "你点击了:" + clickedItem->text());
* });
*
* 【关键注意事项】
* 1. 触发条件:仅用户**单击**触发,代码调用setCurrentItem/setCurrentRow不触发;
* 2. 参数有效性:item始终为有效条目指针(无需判空);
* 3. 选中联动:单击条目会自动将其设为选中项,因此会先触发itemClicked(),再触发currentItemChanged/currentRowChanged;
* 4. 空白区:点击列表空白处(无条目区域)不触发此信号。
*/
/**
* @signal void QListWidget::itemDoubleClicked(QListWidgetItem* item)
* @brief **用户鼠标双击**列表条目时触发的信号(代码操作不触发)
* @details 适配"双击条目执行核心操作"的场景(如打开文件、编辑条目),参数为被双击的条目指针(非nullptr)。
*
* @参数说明:
* @param item - 被双击的条目指针(不会为nullptr,双击空白处不触发)。
*
* @使用示例:
* // 绑定信号,双击条目编辑文本
* connect(ui->listWidget, &QListWidget::itemDoubleClicked, this, [=](QListWidgetItem* doubleItem){
* QString newText = QInputDialog::getText(this, "编辑条目", "修改文本:",
* QLineEdit::Normal, doubleItem->text());
* if (!newText.isEmpty()) {
* doubleItem->setText(newText); // 修改双击条目的文本
* }
* });
*
* 【关键注意事项】
* 1. 触发顺序:双击会先触发itemClicked()(第一次单击),再触发此信号;
* 2. 触发条件:仅用户**双击**触发,代码操作/单击均不触发;
* 3. 交互场景:适合"编辑/打开/查看详情"等需要双击确认的操作。
*/
/**
* @signal void QListWidget::itemEntered(QListWidgetItem* item)
* @brief **鼠标光标进入**列表条目区域时触发的信号(需开启鼠标跟踪)
* @details 悬浮交互信号,用于实现"鼠标悬浮高亮/显示提示"等效果;默认关闭鼠标跟踪,需手动调用setMouseTracking(true)才会触发。
*
* @参数说明:
* @param item - 鼠标进入的条目指针(不会为nullptr)。
*
* @使用示例:
* // 第一步:开启鼠标跟踪
* ui->listWidget->setMouseTracking(true);
* // 第二步:绑定信号,悬浮时高亮条目背景
* connect(ui->listWidget, &QListWidget::itemEntered, this, [=](QListWidgetItem* enterItem){
* enterItem->setBackground(Qt::lightGray); // 悬浮时设浅灰背景
* // 鼠标离开时恢复背景需结合鼠标事件实现
* });
*
* 【关键注意事项】
* 1. 前置条件:必须调用setMouseTracking(true),否则永不触发;
* 2. 触发频率:鼠标在条目间移动时高频触发,避免在信号槽内执行耗时操作;
* 3. 仅进不出:此信号仅响应"进入",鼠标离开条目需结合QMouseEvent手动处理;
* 4. 参数有效性:item始终为有效条目指针(无需判空)。
*/
lw=new QListWidget(this);
ui->lw->setGeometry(100,100,300,300);
//注意,严格注意,我们创建的QListWidgetItem对象,不能是栈上的对象,必须要用new出来的QListWidgetItem
//否则代码结束后,这些局部对象会被自动销毁,QListWidget 里保存的指针就变成了无效地址,所以界面上看不到这些条目。
QListWidgetItem* item1=new QListWidgetItem("1");
ui->lw->addItem(item1);
QListWidgetItem* item2=new QListWidgetItem("2");
ui->lw->addItem(item2);
QListWidgetItem* item3=new QListWidgetItem("3");
ui->lw->addItem(item3);
//我们也可以直接使用addItem方法,直接传入字符串,没有什么特殊要求的话,直接传入字符串还是最方便的
ui->lw->addItem("4");
ui->lw->setSpacing(5);
ui->lw->setItemAlignment(Qt::AlignLeft);
}
Widget::~Widget()
{
delete ui;
}
// 1. 当前选中项改变 (最常用)
void Widget::on_lw_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
// 触发时机:当列表的"当前选中项"发生变化时触发。
// 参数说明:
// current: 新选中的条目指针 (如果取消全选,则为 nullptr)
// previous: 原来选中的条目指针 (如果是首次选中,则为 nullptr)
if (current) {
qDebug() << "[Current Item Changed] 新选中:" << current->text();
// 典型用法:根据选中的条目更新右侧详情面板、启用/禁用按钮
// ui->btnDelete->setEnabled(true);
// showDetails(current->data(Qt::UserRole));
} else {
qDebug() << "[Current Item Changed] 已取消选中";
// ui->btnDelete->setEnabled(false);
}
}
// 2. 当前选中行号改变
void Widget::on_lw_currentRowChanged(int currentRow)
{
// 触发时机:当选中行的索引号发生变化时触发。
// 参数说明:currentRow 是新选中的行号 (从0开始),若取消选中则为 -1。
// 区别:这个信号比 currentItemChanged 更轻量,如果你只需要行号而不需要条目对象,用这个。
qDebug() << "[Current Row Changed] 新行号:" << currentRow;
// 典型用法:记录用户浏览到了第几项,或者用于分页逻辑
// if (currentRow >= 0) {
// int totalCount = ui->lw->count();
// ui->labelStatus->setText(QString("第 %1 / %2 项").arg(currentRow + 1).arg(totalCount));
// }
}
// 3. 条目被单击
void Widget::on_lw_itemClicked(QListWidgetItem *item)
{
// 触发时机:用户鼠标左键单击某个条目时触发(即使该条目已经是当前选中项,再次点击也会触发)。
// 注意:这与 currentItemChanged 不同,如果点击的是已经选中的项,currentItemChanged 不会触发,但 itemClicked 会触发。
qDebug() << "[Item Clicked] 点击了:" << item->text();
// 典型用法:
// 1. 实现"点击已选中项取消选中"的逻辑。
// 2. 播放轻微的点击音效。
// 3. 在触摸屏设备上作为主要交互反馈。
}
// 4. 条目被双击
void Widget::on_lw_itemDoubleClicked(QListWidgetItem *item)
{
// 触发时机:用户快速双击某个条目时触发。
qDebug() << "[Item Double Clicked] 双击了:" << item->text();
// 典型用法:
// 1. 打开详情窗口 / 编辑对话框。
// 2. 启动/运行选中的程序或文件。
// 3. 进入下一级目录(如果是文件浏览器)。
// QDialog dialog; dialog.exec();
}
// 5. 鼠标进入条目区域
void Widget::on_lw_itemEntered(QListWidgetItem *item)
{
// 触发时机:鼠标光标移入某个条目的矩形区域时触发。
// 前提:通常需要确保 viewport()->setMouseTracking(true) 或者直接依赖 Qt 默认行为(QListWidget 通常默认支持)。
qDebug() << "[Item Entered] 鼠标悬停:" << item->text();
// 典型用法:
// 1. 显示 Tooltip 提示详细信息(如果文本被截断)。
// 2. 高亮显示该行(自定义 hover 效果)。
// 3. 动态加载预览图。
// ui->lw->setToolTip(item->data(Qt::UserRole).toString());
}
// 6. 鼠标按下条目
void Widget::on_lw_itemPressed(QListWidgetItem *item)
{
// 触发时机:鼠标按键在条目上按下(尚未释放)时触发。
// 注意:此时还未产生"点击"或"选中"的最终结果,适合做拖拽开始的检测。
qDebug() << "[Item Pressed] 按下了:" << item->text();
// 典型用法:
// 1. 自定义拖拽操作 (Drag & Drop) 的起始判断。
// 2. 右键菜单的预处理(虽然通常用 customContextMenuRequested 信号更好)。
}
// 7. 选中状态改变 (多选模式专用)
void Widget::on_lw_itemSelectionChanged()
{
// 触发时机:当列表中被选中的条目集合发生变化时触发。
// 关键点:
// - 如果 SelectionMode 是 SingleSelection (单选),它 behaves 类似 currentItemChanged。
// - 如果 SelectionMode 是 MultiSelection / ExtendedSelection (多选),这个信号最重要!
// 因为 currentItemChanged 只追踪"当前焦点项",而这个信号追踪"所有被勾选/高亮的项"。
QList<QListWidgetItem*> selectedItems = ui->lw->selectedItems();
qDebug() << "[Selection Changed] 当前共选中" << selectedItems.count() << "项";
// 典型用法:
// 1. 批量操作按钮的状态更新(如:选中多项时才启用"批量删除")。
// 2. 统计选中的数量。
// bool canBatchDelete = (selectedItems.count() > 1);
// ui->btnBatchDelete->setEnabled(canBatchDelete);
}
// 8. 当前条目的文本改变
void Widget::on_lw_currentTextChanged(const QString ¤tText)
{
// 触发时机:当"当前选中项"的文本内容发生改变时触发。
// 注意:这通常发生在条目处于"可编辑"(Editable) 状态,且用户修改完文本失去焦点或按下回车后。
// 如果仅仅是切换了选中项,而新项的文本和旧项一样,可能不会触发(取决于具体实现,通常指内容变更)。
// 修正:在 Qt 标准信号中,这个信号通常是指 **当前选中项变化导致显示的文本变化**,或者 **当前项被编辑后文本变化**。
// 对于 QListWidget,最准确的理解是:当 currentItem 改变,且新旧 currentItem 的 text() 不同时,或者当前项被编辑完成时。
// *注:实际上 QListWidget 的 currentTextChanged 信号主要是响应 currentItem 变化带来的文本变化,类似于 QComboBox。
// 如果是编辑导致的文本变化,通常使用 itemChanged 信号。
qDebug() << "[Current Text Changed] 当前显示文本变为:" << currentText;
// 典型用法:
// 1. 联动另一个只显示文本的标签。
// 2. 根据文本内容过滤其他列表。
}
第七章 综合示例:新增、选中、删除条目
讲完了所有内容,我们最后来做一个综合示例,实现 "通过 QLineEdit 输入文本,点击按钮新增条目;选中条目,点击按钮删除条目;选中变更时打印日志" 的功能 ------ 这是 QListWidget 最经典的应用场景之一。
7.1 场景描述
界面上有:
- 一个 QListWidget(
objectName为listWidget); - 一个 QLineEdit(
objectName为lineEdit),用于输入新条目文本; - 一个 QPushButton(
objectName为pushButton_add),用于新增条目; - 一个 QPushButton(
objectName为pushButton_delete),用于删除选中条目。
功能:
- 点击 "新增" 按钮,将 LineEdit 中的文本添加到 ListWidget 末尾;
- 点击 "删除" 按钮,删除 ListWidget 中当前选中的条目;
- 选中变更时,打印日志;
- LineEdit 为空时不新增。
7.2 代码实现
#include "widget.h"
#include "ui_widget.h"
#include <QListWidgetItem>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 初始化:添加几个初始条目
ui->listWidget->addItem("C++");
ui->listWidget->addItem("Java");
ui->listWidget->addItem("Python");
// 设置条目间距,提升视觉舒适度
ui->listWidget->setSpacing(5);
// 绑定选中变更信号
connect(ui->listWidget, &QListWidget::currentItemChanged,
this, [=](QListWidgetItem* cur, QListWidgetItem* prev){
QString prevText = prev ? prev->text() : "无";
QString curText = cur ? cur->text() : "无";
qDebug() << "选中项变更:" << prevText << " → " << curText;
});
}
Widget::~Widget()
{
delete ui;
}
// 新增按钮槽函数
void Widget::on_pushButton_add_clicked()
{
// 获取 LineEdit 的文本
const QString& text = ui->lineEdit->text();
// 判空:为空则不新增
if (text.isEmpty()) {
return;
}
// 添加到 ListWidget 末尾
ui->listWidget->addItem(text);
// 清空 LineEdit
ui->lineEdit->clear();
}
// 删除按钮槽函数
void Widget::on_pushButton_delete_clicked()
{
// 获取当前选中行号
int row = ui->listWidget->currentRow();
// 判空:无选中则不删除
if (row == -1) {
return;
}
// 删除指定行的条目
QListWidgetItem* deletedItem = ui->listWidget->takeItem(row);
if (deletedItem != nullptr) {
qDebug() << "删除条目:" << deletedItem->text();
delete deletedItem; // 必须手动 delete!
deletedItem = nullptr;
}
}
完整示例代码:
cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//OK,那么本文件我们就来正式的学习QListWidget的核心属性,其实也不多
//也不难,大部分我们之前都有接触过·~~·
/**
* @class QListWidget
* @brief Qt中用于展示纵向列表的可视化控件,基于项(QListWidgetItem)管理列表内容
* @details QListWidget以行式布局展示多个条目(QListWidgetItem),支持条目选中、排序、换行、对齐方式定制、间距调整等功能;
* 每个条目可独立配置文本/图标/样式,提供丰富的增删改查方法和交互信号,是Qt中最常用的列表展示控件之一。
*
* 【核心特征】
* 1. 条目管理:支持添加、插入、删除、选中条目,可通过行号/条目对象精准操作;
* 2. 视觉定制:支持条目对齐、间距、选中矩形显隐、换行等视觉配置;
* 3. 交互反馈:提供选中变更、点击、双击、鼠标进入等核心交互信号;
* 4. 功能扩展:支持列表排序、行数统计、当前选中项快速获取。
*/
// ============================== 核心属性详解 ==============================
/**
* @property QListWidget::currentRow
* @brief QListWidget当前被选中条目的行号属性
* @details 该属性表征列表中当前激活选中的条目行号,默认值为-1(无选中条目);
* 行号从0开始计数(第一行=0,第二行=1...),修改该属性会触发currentRowChanged()信号。
*
* 【关联API详解】
* 1. int currentRow() const → 获取当前选中条目的行号(无选中返回-1);
* 2. void setCurrentRow(int row) → 设置指定行号的条目为当前选中项(行号超出范围则取消选中)。
*
* @使用示例:
* // 获取当前选中行号
* int selectedRow = ui->listWidget->currentRow();
* qDebug() << "当前选中行:" << selectedRow;
*
* // 设置选中第2行(索引1)
* ui->listWidget->setCurrentRow(1);
*
* 【关键注意事项】
* 1. 行号规则:行号从0开始,若列表为空或无选中项,返回-1;
* 2. 联动currentItem:修改currentRow会同步更新currentItem,反之亦然;
* 3. 范围约束:设置行号超出[0, count-1]时,会取消所有选中,currentRow变为-1。
*/
/**
* @property QListWidget::count
* @brief QListWidget列表中条目总行数属性
* @details 该属性只读,表征列表中当前包含的QListWidgetItem总数,默认值为0(空列表);
* 增删条目时会自动更新,是统计列表条目数量的核心属性。
*
* 【关联API详解】
* 1. int count() const → 获取列表条目总行数;
* 2. bool isEmpty() const → 等价于count() == 0,快速判断列表是否为空。
*
* @使用示例:
* // 统计列表总行数
* int totalRows = ui->listWidget->count();
* qDebug() << "列表总行数:" << totalRows;
*
* // 判断列表是否为空
* if (ui->listWidget->isEmpty()) {
* qDebug() << "列表为空";
* }
*
* 【关键注意事项】
* 1. 只读属性:无法直接修改,仅通过addItem/insertItem/takeItem等方法间接变更;
* 2. 实时更新:增删条目后立即生效,无需手动刷新;
* 3. 行号关联:有效行号范围为[0, count()-1],超出该范围的行号操作无效。
*/
/**
* @property QListWidget::sortingEnabled
* @brief QListWidget是否允许列表自动排序的属性
* @details 该属性控制列表条目是否按文本内容自动排序,默认值为false(不排序);
* 设为true时,列表会按条目文本的字母/数字顺序升序排列,新增/修改条目文本时会自动重新排序。
*
* 【关联API详解】
* 1. bool isSortingEnabled() const → 判断是否开启自动排序;
* 2. void setSortingEnabled(bool enable) → 设置是否开启自动排序;
* 3. void sortItems(Qt::SortOrder order = Qt::AscendingOrder) → 手动触发排序(可指定升序/降序)。
*
* @使用示例:
* // 开启自动排序(升序)
* ui->listWidget->setSortingEnabled(true);
*
* // 手动触发降序排序(即使sortingEnabled=false也生效)
* ui->listWidget->sortItems(Qt::DescendingOrder);
*
* 【关键注意事项】
* 1. 排序规则:默认按文本Unicode编码升序排列,中文按拼音/Unicode排序;
* 2. 行号变化:排序后条目行号会重新分配,原行号失效;
* 3. 性能影响:大量条目(如1000+)开启自动排序会轻微影响增删效率,建议批量增删后再开启。
*/
/**
* @property QListWidget::isWrapping
* @brief QListWidget是否允许条目换行显示的属性
* @details 该属性控制列表条目是否在控件宽度不足时自动换行,默认值为false(不换行);
* 设为true时,条目会从左到右排列,一行放不下则自动换行,形成多列布局(类似流式布局)。
*
* 【关联API详解】
* 1. bool isWrapping() const → 判断是否允许换行;
* 2. void setWrapping(bool wrap) → 设置是否允许换行。
*
* @使用示例:
* // 开启换行,条目超出宽度自动换行
* ui->listWidget->setWrapping(true);
* ui->listWidget->setFixedWidth(200); // 固定列表宽度,触发换行效果
*
* 【关键注意事项】
* 1. 布局影响:换行仅在列表为水平流式布局时生效,默认纵向列表需配合setViewMode(QListView::IconMode)使用;
* 2. 视觉适配:换行后条目按"行-列"排列,count()仍统计总条目数,currentRow()按视觉行号计算;
* 3. 间距配合:换行后可通过spacing属性调整条目间的水平/垂直间距。
*/
/**
* @property QListWidget::itemAlignment
* @brief QListWidget列表条目整体的对齐方式属性
* @details 该属性控制所有条目在列表控件内的整体对齐位置(水平+垂直),默认值为Qt::AlignLeft | Qt::AlignTop;
* 区别于QListWidgetItem::setTextAlignment(单个条目内文本的对齐),该属性是条目整体在控件中的对齐。
*
* 【核心枚举值(Qt::Alignment)】
* | 枚举值 | 功能说明 |
* |-----------------------|--------------------------------------------------------------------------|
* | Qt::AlignLeft | 水平左对齐(默认); |
* | Qt::AlignRight | 水平右对齐; |
* | Qt::AlignHCenter | 水平居中; |
* | Qt::AlignCenter | 水平+垂直居中; |
* | Qt::AlignTop | 垂直顶部对齐(默认); |
* | Qt::AlignBottom | 垂直底部对齐; |
* | Qt::AlignVCenter | 垂直居中; |
*
* 【关联API详解】
* 1. Qt::Alignment itemAlignment() const → 获取条目整体对齐方式;
* 2. void setItemAlignment(Qt::Alignment alignment) → 设置条目整体对齐方式。
*
* @使用示例:
* // 设置所有条目在列表中水平居中+垂直居中
* ui->listWidget->setItemAlignment(Qt::AlignCenter);
* ui->listWidget->setFixedSize(300, 200); // 固定控件尺寸,对齐效果更明显
*
* 【关键注意事项】
* 1. 层级区别:itemAlignment(条目整体在控件中对齐)≠ setTextAlignment(文本在条目内对齐);
* 2. 换行适配:开启wrapping时,对齐方式控制每一行条目整体的对齐;
* 3. 尺寸影响:控件尺寸需大于条目总尺寸,才能体现明显的对齐效果。
*/
/**
* @property QListWidget::selectRectVisible
* @brief QListWidget选中条目对应的矩形框是否可见的属性
* @details 该属性控制选中条目周围是否显示高亮矩形框,默认值为true(可见);
* 设为false时,选中条目仍会触发选中信号,但视觉上无矩形框高亮(可通过QSS自定义选中样式替代)。
*
* 【关联API详解】
* 1. bool isSelectRectVisible() const → 判断选中矩形框是否可见;
* 2. void setSelectRectVisible(bool visible) → 设置选中矩形框是否可见。
*
* @使用示例:
* // 隐藏选中矩形框(仅通过文本颜色区分选中状态)
* ui->listWidget->setSelectRectVisible(false);
* // 自定义选中条目文本颜色
* QListWidgetItem* item = ui->listWidget->item(0);
* item->setForeground(Qt::red); // 选中时手动修改颜色
*
* 【关键注意事项】
* 1. 仅视觉影响:隐藏矩形框不影响选中逻辑和信号触发;
* 2. 样式覆盖:若通过QSS自定义了QListWidget::item:selected样式,该属性可能被覆盖;
* 3. 交互兼容:即使隐藏矩形框,条目仍可被选中/点击,不影响交互功能。
*/
/**
* @property QListWidget::spacing
* @brief QListWidget列表条目之间的间距属性(像素)
* @details 该属性控制相邻条目之间的水平/垂直间距,默认值为0(无间距);
* 开启wrapping(换行)时,同时控制水平和垂直间距;未开启时仅控制垂直间距。
*
* 【关联API详解】
* 1. int spacing() const → 获取条目之间的间距(像素);
* 2. void setSpacing(int space) → 设置条目间距(建议值≥0,负值自动修正为0)。
*
* @使用示例:
* // 设置条目间距为10像素(垂直/水平均为10)
* ui->listWidget->setSpacing(10);
*
* 【关键注意事项】
* 1. 单位:间距单位为像素,数值越大条目间空隙越大;
* 2. 换行适配:开启wrapping时,spacing同时控制行内条目水平间距和行之间的垂直间距;
* 3. 布局影响:间距会增加列表整体尺寸,需结合控件大小适配。
*/
// ============================== 核心方法详解 ==============================
/**
* @fn void QListWidget::addItem(const QString& label)
* @fn void QListWidget::addItem(QListWidgetItem *item)
* @brief QListWidget向列表末尾添加条目(两种重载形式)
* @details 该方法是添加条目的基础方式,直接将条目追加到列表最后一行;
* 重载1通过文本快速创建默认条目,重载2添加自定义配置的QListWidgetItem对象。
*
* @参数说明:
* @param label - QString类型,重载1的参数,条目显示的文本内容;
* @param item - QListWidgetItem*类型,重载2的参数,自定义配置的条目对象(需手动创建)。
*
* @使用示例:
* // 重载1:快速添加文本条目
* ui->listWidget->addItem("条目1");
* ui->listWidget->addItem("条目2");
*
* // 重载2:添加自定义配置的条目
* QListWidgetItem* customItem = new QListWidgetItem("自定义条目");
* customItem->setIcon(QIcon(":/images/icon.png")); // 设置图标
* customItem->setFont(QFont("微软雅黑", 12)); // 设置字体
* ui->listWidget->addItem(customItem);
*
* 【关键注意事项】
* 1. 内存管理:通过重载2添加的item,所有权移交至QListWidget,无需手动delete(删除条目用takeItem);
* 2. 排序影响:若开启sortingEnabled=true,添加的条目会自动排序,不一定在末尾;
* 3. 空值处理:label为空字符串时,条目仍会添加(显示为空行),item为nullptr时无任何操作。
*/
/**
* @fn QListWidgetItem* QListWidget::currentItem() const
* @brief QListWidget获取当前选中条目的对象指针
* @details 该方法返回当前激活选中的QListWidgetItem对象,无选中条目时返回nullptr;
* 是通过条目对象操作选中项的核心方法(如修改选中项文本/图标)。
*
* @返回值说明:
* @return QListWidgetItem* - 当前选中条目指针(无选中返回nullptr)。
*
* @使用示例:
* // 获取当前选中条目并修改其文本
* QListWidgetItem* selectedItem = ui->listWidget->currentItem();
* if (selectedItem != nullptr) { // 判空避免空指针
* selectedItem->setText("已选中:" + selectedItem->text());
* }
*
* 【关键注意事项】
* 1. 判空必须:列表为空或无选中项时返回nullptr,直接操作会导致程序崩溃;
* 2. 联动currentRow:currentItem()和currentRow()一一对应(item行号=currentRow());
* 3. 只读指针:返回的是条目对象指针,可修改条目属性,但不可手动delete(需用takeItem)。
*/
/**
* @fn void QListWidget::setCurrentItem(QListWidgetItem* item)
* @brief QListWidget设置指定条目为当前选中项
* @details 该方法通过条目对象精准选中指定项,item为nullptr时取消所有选中;
* 选中后会触发currentItemChanged()和currentRowChanged()信号。
*
* @参数说明:
* @param item - QListWidgetItem*类型,要选中的条目对象(nullptr取消选中)。
*
* @使用示例:
* // 创建条目并设置为选中项
* QListWidgetItem* targetItem = new QListWidgetItem("目标条目");
* ui->listWidget->addItem(targetItem);
* ui->listWidget->setCurrentItem(targetItem); // 选中该条目
*
* 【关键注意事项】
* 1. 有效性检查:item必须是当前列表中的条目(已通过addItem/insertItem添加),否则无效果;
* 2. 信号触发:设置后会依次触发currentItemChanged()和currentRowChanged();
* 3. 空值处理:item为nullptr时,currentRow()变为-1,取消所有选中。
*/
/**
* @fn void QListWidget::setCurrentRow(int row)
* @brief QListWidget设置指定行号的条目为当前选中项
* @details 该方法通过行号快速选中条目,是setCurrentItem()的行号版封装;
* 行号超出[0, count()-1]范围时,取消所有选中(currentRow()=-1)。
*
* @参数说明:
* @param row - int类型,要选中的条目行号(从0开始)。
*
* @使用示例:
* // 选中第3行(索引2)的条目
* ui->listWidget->setCurrentRow(2);
*
* 【关键注意事项】
* 1. 行号规则:行号从0开始,count()为总行数,有效行号范围[0, count()-1];
* 2. 等价操作:setCurrentRow(row) 等价于 setCurrentItem(item(row));
* 3. 信号触发:设置有效行号时触发currentRowChanged()和currentItemChanged()。
*/
/**
* @fn void QListWidget::insertItem(int row, const QString& label)
* @fn void QListWidget::insertItem(int row, QListWidgetItem *item)
* @brief QListWidget在指定行号位置插入条目(两种重载形式)
* @details 该方法区别于addItem(仅追加末尾),可在任意行号位置插入条目;
* 行号超出范围时,自动追加到末尾(row>count())或插入到开头(row<0)。
*
* @参数说明:
* @param row - int类型,插入位置的行号(从0开始);
* @param label - QString类型,重载1的参数,条目显示文本;
* @param item - QListWidgetItem*类型,重载2的参数,自定义条目对象。
*
* @使用示例:
* // 重载1:在第1行(索引0)插入文本条目
* ui->listWidget->insertItem(0, "插入到开头的条目");
*
* // 重载2:在第2行(索引1)插入自定义条目
* QListWidgetItem* insertItem = new QListWidgetItem("插入条目");
* insertItem->setIcon(QIcon(":/images/insert.png"));
* ui->listWidget->insertItem(1, insertItem);
*
* 【关键注意事项】
* 1. 行号容错:row<0 → 插入到开头;row>count() → 追加到末尾;
* 2. 内存管理:重载2的item所有权移交至列表,无需手动delete;
* 3. 行号偏移:插入位置后的条目行号自动+1(如在索引1插入,原索引1的条目变为索引2)。
*/
/**
* @fn QListWidgetItem* QListWidget::item(int row) const
* @brief QListWidget通过行号获取对应条目对象指针
* @details 该方法是"行号→条目"的核心映射方法,可精准获取指定行的条目进行属性修改;
* 行号超出范围时返回nullptr。
*
* @参数说明:
* @param row - int类型,要获取的条目行号(从0开始)。
*
* @返回值说明:
* @return QListWidgetItem* - 指定行的条目指针(行号无效返回nullptr)。
*
* @使用示例:
* // 获取第2行(索引1)的条目并修改图标
* QListWidgetItem* targetItem = ui->listWidget->item(1);
* if (targetItem != nullptr) {
* targetItem->setIcon(QIcon(":/images/target.png"));
* }
*
* 【关键注意事项】
* 1. 判空必须:行号无效时返回nullptr,直接操作会导致崩溃;
* 2. 实时性:行号随增删/排序动态变化,需注意操作时机;
* 3. 只读指针:可修改条目属性,但不可手动delete。
*/
/**
* @fn QListWidgetItem* QListWidget::takeItem(int row)
* @brief QListWidget删除指定行号的条目,并返回该条目指针
* @details 该方法是删除条目的核心方法,区别于直接delete(会导致内存泄漏/崩溃);
* 删除后该行后续条目行号自动-1,count()减1。
*
* @参数说明:
* @param row - int类型,要删除的条目行号(从0开始)。
*
* @返回值说明:
* @return QListWidgetItem* - 被删除的条目指针(行号无效返回nullptr)。
*
* @使用示例:
* // 删除第1行(索引0)的条目,并释放其内存
* QListWidgetItem* deletedItem = ui->listWidget->takeItem(0);
* if (deletedItem != nullptr) {
* delete deletedItem; // 必须手动释放内存,否则内存泄漏
* deletedItem = nullptr;
* }
*
* 【关键注意事项】
* 1. 内存管理:takeItem仅将条目从列表中移除,需手动delete返回的指针释放内存;
* 2. 行号偏移:删除条目后,后续条目行号自动-1(如删除索引1,原索引2变为索引1);
* 3. 选中状态:若删除的是当前选中条目,currentRow()变为-1,取消选中。
*/
// ============================== 核心信号详解 ==============================
/**
* @signal void QListWidget::currentItemChanged(QListWidgetItem* current, QListWidgetItem* old)
* @brief QListWidget选中条目变更时触发的信号
* @details 该信号反馈选中条目的变更,触发场景包括:用户点击不同条目、代码调用setCurrentItem/setCurrentRow、删除选中条目;
* 可同时获取当前选中条目和上一个选中条目,便于对比处理。
*
* @参数说明:
* @param current - QListWidgetItem*,变更后的当前选中条目(无选中则为nullptr);
* @param old - QListWidgetItem*,变更前的上一个选中条目(无则为nullptr)。
*
* @使用示例:
* // 绑定信号,打印选中条目变更
* connect(ui->listWidget, &QListWidget::currentItemChanged, this, [=](QListWidgetItem* cur, QListWidgetItem* prev){
* QString prevText = prev ? prev->text() : "无";
* QString curText = cur ? cur->text() : "无";
* qDebug() << "选中项变更:" << prevText << " → " << curText;
* });
*
* 【关键注意事项】
* 1. 判空处理:current/old可能为nullptr(如首次选中/取消选中),需先判空再操作;
* 2. 触发时机:与currentRowChanged()同步触发,先触发currentItemChanged()再触发currentRowChanged();
* 3. 无重复触发:选中同一条目时(如重复点击),不会触发该信号。
*/
/**
* @signal void QListWidget::currentRowChanged(int currentRow)
* @brief QListWidget选中条目行号变更时触发的信号
* @details 该信号是currentItemChanged()的行号版封装,仅反馈行号变更,更适合仅需行号的场景;
* 参数为新的选中行号(无选中则为-1)。
*
* @参数说明:
* @param currentRow - int类型,变更后的选中行号(无选中返回-1)。
*
* @使用示例:
* // 绑定信号,更新标签显示选中行号
* connect(ui->listWidget, &QListWidget::currentRowChanged, this, [=](int row){
* if (row == -1) {
* ui->labSelected->setText("无选中项");
* } else {
* ui->labSelected->setText(QString("选中第%1行").arg(row+1)); // 行号+1适配用户习惯
* }
* });
*
* 【关键注意事项】
* 1. 行号规则:参数为程序内部行号(从0开始),展示给用户时建议+1;
* 2. 触发场景:所有导致选中项变更的操作都会触发,包括删除选中条目(row=-1);
* 3. 简洁性:仅需行号时优先使用该信号,无需处理条目对象判空。
*/
/**
* @signal void QListWidget::itemClicked(QListWidgetItem* item)
* @brief QListWidget点击任意条目时触发的信号
* @details 该信号仅在用户鼠标点击条目时触发(代码选中不会触发),参数为被点击的条目指针;
* 是响应"点击条目"交互的核心信号。
*
* @参数说明:
* @param item - QListWidgetItem*,被点击的条目指针(不会为nullptr)。
*
* @使用示例:
* // 绑定信号,点击条目时弹出文本提示
* connect(ui->listWidget, &QListWidget::itemClicked, this, [=](QListWidgetItem* clickedItem){
* QMessageBox::information(this, "点击提示", "你点击了:" + clickedItem->text());
* });
*
* 【关键注意事项】
* 1. 触发条件:仅用户鼠标点击触发,代码调用setCurrentItem/setCurrentRow不会触发;
* 2. 参数有效性:item始终为有效条目指针(点击空白处不会触发该信号);
* 3. 与选中联动:点击条目会自动将其设为当前选中项,因此会先触发itemClicked(),再触发currentItemChanged()/currentRowChanged()。
*/
/**
* @signal void QListWidget::itemDoubleClicked(QListWidgetItem* item)
* @brief QListWidget双击任意条目时触发的信号
* @details 该信号仅在用户鼠标双击条目时触发,参数为被双击的条目指针;
* 常用于"双击条目执行操作"场景(如打开文件、编辑条目)。
*
* @参数说明:
* @param item - QListWidgetItem*,被双击的条目指针(不会为nullptr)。
*
* @使用示例:
* // 绑定信号,双击条目时编辑文本
* connect(ui->listWidget, &QListWidget::itemDoubleClicked, this, [=](QListWidgetItem* doubleClickedItem){
* QString newText = QInputDialog::getText(this, "编辑条目", "修改文本:",
* QLineEdit::Normal, doubleClickedItem->text());
* if (!newText.isEmpty()) {
* doubleClickedItem->setText(newText);
* }
* });
*
* 【关键注意事项】
* 1. 触发条件:仅用户双击触发,单击/代码选中不会触发;
* 2. 与单击兼容:双击会先触发itemClicked()(第一次单击),再触发itemDoubleClicked();
* 3. 交互场景:适合"查看详情/编辑/打开"等需要双击确认的操作。
*/
/**
* @signal void QListWidget::itemEntered(QListWidgetItem* item)
* @brief QListWidget鼠标光标进入条目区域时触发的信号
* @details 该信号仅在鼠标光标移入条目范围内时触发,需先开启鼠标跟踪(setMouseTracking(true));
* 常用于"鼠标悬浮提示/高亮"场景。
*
* @参数说明:
* @param item - QListWidgetItem*,鼠标进入的条目指针(不会为nullptr)。
*
* @使用示例:
* // 开启鼠标跟踪,绑定itemEntered信号实现悬浮高亮
* ui->listWidget->setMouseTracking(true);
* connect(ui->listWidget, &QListWidget::itemEntered, this, [=](QListWidgetItem* enteredItem){
* enteredItem->setBackground(Qt::lightGray); // 悬浮时背景变浅灰
* // 离开时恢复(需结合鼠标离开事件)
* });
*
* 【关键注意事项】
* 1. 前置条件:必须调用setMouseTracking(true),否则不会触发;
* 2. 触发频率:鼠标在条目间移动时会高频触发,需避免耗时操作;
* 3. 离开处理:该信号仅处理进入,离开条目需结合QMouseEvent手动实现。
*/
}
Widget::~Widget()
{
delete ui;
}
第八章 全文总结与学习建议
恭喜你!终于看完了这篇QListWidget 与 QListWidgetItem 详细解析!
如果你跟着文章一步步敲了代码,做了练习,那么现在你已经完全掌握了它们的核心内容:
- 你知道了 QListWidget 是纵向列表控件,QListWidgetItem 是列表中的单个条目;
- 你会用 QListWidgetItem 的
setText、setFont、setIcon、setHidden、setSizeHint、setSelected、setTextAlignment定制条目; - 你会用 QListWidget 的
currentRow、count、itemAlignment、spacing、sortingEnabled、isWrapping配置列表; - 你会用
addItem、insertItem、takeItem、item、currentItem操作条目; - 你会绑定
currentItemChanged、itemClicked、itemDoubleClicked、itemEntered等信号实现交互; - 你知道了QListWidgetItem 必须用 new 创建! takeItem 后必须手动 delete! currentItem 必须先判空! 行号从 0 开始! 这些超级重要的注意事项。
毫不夸张地说,掌握了这些内容,你就掌握了 QListWidget 开发的 95% 以上的需求!
8.1 核心要点回顾
在结束之前,我们最后再回顾一下这篇文章的核心要点,特别是那些最容易踩坑的地方:
- QListWidgetItem 必须用 new 创建!(超级重要!开篇就讲!):不能是栈对象!
- takeItem 后必须手动 delete!(超级重要!):否则内存泄漏!
- currentItem、currentItemChanged 的参数必须先判空!(超级重要!):否则程序崩溃!
- 行号从 0 开始!(超级重要!说三遍!):用户视角需 +1!
- itemEntered 必须先调用 setMouseTracking (true)!(超级重要!);
- sortingEnabled 开启后原行号失效!(超级重要!);
- itemClicked 仅用户单击触发,代码选中不触发!(超级重要!);
- QListWidget::itemAlignment 和 QListWidgetItem::setTextAlignment 是不同层级的对齐!(超级重要!);
- addItem 的自定义条目无需手动 delete,列表接管所有权!(超级重要!);
- count 是只读的,isEmpty () 更便捷!。
8.2 最后的话
编程学习没有捷径,唯手熟尔。QListWidget 和 QListWidgetItem 的内容虽然不少,但只要你多敲代码、多做练习、多踩坑、多排查,很快就能熟练掌握。
这篇文章虽然很长,但我相信,如果你认真看完了,跟着敲了代码,你一定会对它们有一个极其深刻的理解,再也不会为列表开发发愁。
感谢你阅读这篇文章,希望它能帮到你。我们下一篇 Qt 教程再见