当前位置: 首页 > news >正文

Qt自定义列表项与QListWidget学习

Qt自定义列表项与QListWidget学习

1. 项目概述

本项目实现了一个模拟QQ群成员列表的界面,主要展示了如何使用Qt中的QListWidget控件结合自定义控件来创建复杂的列表项。项目的主要特点包括:

  • 使用QListWidget作为列表容器
  • 创建自定义的QQItem控件作为列表项
  • 使用Qt样式表(QSS)美化界面
  • 使用Qt资源系统管理图片资源

2. 项目结构

42/
├── 42.pro           # 项目文件
├── main.cpp         # 主函数入口
├── widget.h         # 主窗口头文件
├── widget.cpp       # 主窗口实现
├── widget.ui        # 主窗口界面设计
├── qqitem.h         # 自定义列表项头文件
├── qqitem.cpp       # 自定义列表项实现
├── qqitem.ui        # 自定义列表项界面设计
├── res.qrc          # 资源文件
└── icons/           # 图标资源目录├── icon0.jpg    # 头像图片├── icon1.jpg    # 头像图片├── icon2.jpg    # 头像图片├── icon3.jpg    # 头像图片├── phone.png    # 电话图标└── search.png   # 搜索图标

3. 主窗口设计

3.1 界面设计 (widget.ui)

主窗口界面使用Qt Designer设计,主要包含以下元素:

  • 一个标题标签,显示群成员数量信息
  • 一个搜索框,包含搜索图标按钮和文本输入框
  • 一个QListWidget控件,用于显示群成员列表

界面使用垂直布局(QVBoxLayout)组织这些元素,搜索框内部使用水平布局(QHBoxLayout)。

<!-- widget.ui 主要结构 -->
<layout class="QVBoxLayout" name="verticalLayout"><item><widget class="QLabel" name="label"><!-- 标题标签属性设置 --></widget></item><item><layout class="QHBoxLayout" name="horizontalLayout"><item><widget class="QPushButton" name="pushButton"><!-- 搜索按钮属性设置 --></widget></item><item><widget class="QLineEdit" name="lineEdit"><!-- 搜索输入框属性设置 --></widget></item></layout></item><item><widget class="QListWidget" name="listWidget"><!-- 列表控件属性设置 --></widget></item>
</layout>

3.2 样式设置

主窗口中使用了Qt样式表(QSS)来美化界面元素:

/* 搜索按钮样式 */
QPushButton { border-image: url(:/icons/search.png) }/* 搜索输入框样式 */
QLineEdit { background: transparent; border: none }/* 列表项样式 */
QListWidget::item { height: 65px }
QListWidget::item:selected { background-color: rgb(200, 200, 200) }
QListWidget::item:hover { background-color: rgb(220, 220, 220) }

这些样式设置了:

  • 搜索按钮使用图片作为背景
  • 搜索输入框透明无边框
  • 列表项高度固定为65px
  • 列表项选中和悬停时的背景颜色

4. 自定义列表项设计

4.1 界面设计 (qqitem.ui)

自定义列表项使用Qt Designer设计,包含以下元素:

  • 一个头像图片标签(QLabel)
  • 一个电话图标标签(QLabel),可选显示
  • 一个名称标签(QLabel)

这些元素使用水平布局(QHBoxLayout)组织,并添加了适当的间距。

<!-- qqitem.ui 主要结构 -->
<layout class="QHBoxLayout" name="horizontalLayout"><item><spacer name="horizontalSpacer"><!-- 左侧间距 --></spacer></item><item><widget class="QWidget" name="widget" native="true"><!-- 头像容器 --><widget class="QLabel" name="icon"><!-- 头像标签属性设置 --></widget><widget class="QLabel" name="phone"><!-- 电话图标标签属性设置 --></widget></widget></item><item><widget class="QLabel" name="name"><!-- 名称标签属性设置 --></widget></item><item><spacer name="horizontalSpacer_2"><!-- 右侧间距 --></spacer></item>
</layout>

4.2 样式设置

自定义列表项中也使用了Qt样式表(QSS)来美化界面元素:

/* 头像容器样式 */
QWidget { background: transparent; border-radius: 10px }/* 头像标签样式 */
QLabel { background-color: darkgray; border-radius: 10px }/* 名称标签样式 */
QLabel { color: darkgray; font-size: 20px }

这些样式设置了:

  • 头像容器透明背景,圆角边框
  • 头像标签深灰色背景,圆角边框
  • 名称标签深灰色文字,20px字体大小

5. 代码实现

5.1 自定义列表项类 (QQItem)

5.1.1 类定义 (qqitem.h)
#ifndef QQITEM_H
#define QQITEM_H#include <QWidget>namespace Ui {
class QQItem;
}class QQItem : public QWidget
{Q_OBJECTpublic:explicit QQItem(QString icon, bool flag, QString name, QWidget *parent = nullptr);~QQItem();private:Ui::QQItem *ui;
};#endif // QQITEM_H

自定义列表项类继承自QWidget,构造函数接受三个参数:

  • icon:头像图片路径
  • flag:是否显示电话图标
  • name:成员名称
5.1.2 类实现 (qqitem.cpp)
#include "qqitem.h"
#include "ui_qqitem.h"QQItem::QQItem(QString icon, bool flag, QString name, QWidget *parent) :QWidget(parent),ui(new Ui::QQItem)
{ui->setupUi(this);QImage image(icon);ui->icon->setPixmap(QPixmap::fromImage(image.scaled(ui->icon->width(), ui->icon->height())));QImage image2(":/icons/phone.png");ui->phone->setPixmap(QPixmap::fromImage(image2.scaled(ui->phone->width(), ui->phone->height())));ui->phone->setVisible(flag);ui->name->setText(name);
}QQItem::~QQItem()
{delete ui;
}

构造函数中的主要操作:

  1. 加载头像图片,并设置到icon标签
  2. 加载电话图标,并根据flag参数决定是否显示
  3. 设置成员名称到name标签

5.2 主窗口类 (Widget)

5.2.1 类定义 (widget.h)
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;
};
#endif // WIDGET_H
5.2.2 类实现 (widget.cpp)
#include "widget.h"
#include "ui_widget.h"
#include "qqitem.h"#include <QListWidgetItem>class QQItem;Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setLayout(ui->verticalLayout);QQItem *qqItem = new QQItem(":/icons/icon1.jpg", true, "风子兰特");QQItem *qqItem1 = new QQItem(":/icons/icon0.jpg", false, "LIYOU");QQItem *qqItem2 = new QQItem(":/icons/icon2.jpg", false, "简单一点");QQItem *qqItem3 = new QQItem(":/icons/icon3.jpg", true, "Nov");QListWidgetItem *item0 = new QListWidgetItem;QListWidgetItem *item1 = new QListWidgetItem;QListWidgetItem *item2 = new QListWidgetItem;QListWidgetItem *item3 = new QListWidgetItem;ui->listWidget->addItem(item0);ui->listWidget->addItem(item1);ui->listWidget->addItem(item2);ui->listWidget->addItem(item3);ui->listWidget->setItemWidget(item0, qqItem);ui->listWidget->setItemWidget(item1, qqItem1);ui->listWidget->setItemWidget(item2, qqItem2);ui->listWidget->setItemWidget(item3, qqItem3);
}Widget::~Widget()
{delete ui;
}

主窗口构造函数中的主要操作:

  1. 创建4个自定义列表项(QQItem),设置不同的头像、电话图标显示状态和名称
  2. 创建4个列表项(QListWidgetItem)
  3. 将列表项添加到列表控件(QListWidget)
  4. 将自定义列表项设置为列表项的控件

5.3 主函数 (main.cpp)

#include "widget.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

主函数创建并显示主窗口,然后进入应用程序事件循环。

6. 资源管理

6.1 资源文件 (res.qrc)

<RCC><qresource prefix="/"><file>icons/icon0.jpg</file><file>icons/icon1.jpg</file><file>icons/icon2.jpg</file><file>icons/icon3.jpg</file><file>icons/phone.png</file><file>icons/search.png</file></qresource>
</RCC>

资源文件定义了项目中使用的图片资源,包括头像图片和图标。这些资源可以通过:/icons/xxx的路径在代码中访问。

7. QListWidget使用技巧

7.1 基本用法

// 创建列表项
QListWidgetItem *item = new QListWidgetItem;// 添加列表项到列表控件
listWidget->addItem(item);// 设置列表项的文本
item->setText("列表项文本");// 设置列表项的图标
item->setIcon(QIcon("图标路径"));// 设置列表项的工具提示
item->setToolTip("工具提示文本");// 设置列表项的数据
item->setData(Qt::UserRole, QVariant("自定义数据"));

7.2 自定义列表项

// 创建自定义控件
MyCustomWidget *widget = new MyCustomWidget;// 创建列表项
QListWidgetItem *item = new QListWidgetItem;// 添加列表项到列表控件
listWidget->addItem(item);// 设置列表项的大小
item->setSizeHint(widget->sizeHint());// 将自定义控件设置为列表项的控件
listWidget->setItemWidget(item, widget);

7.3 样式设置

/* 列表控件样式 */
QListWidget {background-color: white;border: 1px solid gray;outline: none; /* 去除焦点边框 */
}/* 列表项样式 */
QListWidget::item {height: 50px; /* 固定高度 */padding: 5px; /* 内边距 */border-bottom: 1px solid lightgray; /* 底部边框 */
}/* 选中列表项样式 */
QListWidget::item:selected {background-color: #e0e0e0; /* 选中背景色 */color: black; /* 选中文字颜色 */
}/* 悬停列表项样式 */
QListWidget::item:hover {background-color: #f0f0f0; /* 悬停背景色 */
}

7.4 信号与槽

// 连接列表项点击信号
connect(listWidget, &QListWidget::itemClicked, this, &MyClass::onItemClicked);// 连接列表项双击信号
connect(listWidget, &QListWidget::itemDoubleClicked, this, &MyClass::onItemDoubleClicked);// 连接当前项改变信号
connect(listWidget, &QListWidget::currentItemChanged, this, &MyClass::onCurrentItemChanged);// 槽函数实现
void MyClass::onItemClicked(QListWidgetItem *item)
{// 处理列表项点击事件int row = listWidget->row(item); // 获取行号QString text = item->text(); // 获取文本QVariant data = item->data(Qt::UserRole); // 获取自定义数据
}

8. 实现自定义列表项的步骤

  1. 创建自定义控件类

    • 继承QWidget或其他适合的控件类
    • 设计控件的界面(使用Qt Designer或代码)
    • 实现必要的功能和交互
  2. 在主窗口中使用自定义列表项

    • 创建QListWidgetItem对象
    • 创建自定义控件对象
    • 将列表项添加到QListWidget
    • 使用setItemWidget将自定义控件设置为列表项的控件
  3. 设置样式和交互

    • 使用Qt样式表(QSS)美化界面
    • 实现必要的信号与槽连接
    • 处理用户交互事件

10. 扩展功能示例

10.1 添加搜索功能

// 连接搜索输入框的文本变化信号
connect(ui->lineEdit, &QLineEdit::textChanged, this, &Widget::onSearchTextChanged);// 搜索功能实现
void Widget::onSearchTextChanged(const QString &text)
{// 遍历所有列表项for (int i = 0; i < ui->listWidget->count(); ++i){QListWidgetItem *item = ui->listWidget->item(i);QWidget *widget = ui->listWidget->itemWidget(item);QQItem *qqItem = qobject_cast<QQItem*>(widget);// 获取名称标签的文本(假设有getName方法)QString name = qqItem->getName();// 根据搜索文本显示或隐藏列表项if (text.isEmpty() || name.contains(text, Qt::CaseInsensitive)){item->setHidden(false);}else{item->setHidden(true);}}
}

10.2 添加右键菜单

// 重写上下文菜单事件
void Widget::contextMenuEvent(QContextMenuEvent *event)
{QListWidgetItem *item = ui->listWidget->itemAt(ui->listWidget->mapFromGlobal(event->globalPos()));if (item){QMenu menu(this);QAction *viewAction = menu.addAction("查看资料");QAction *chatAction = menu.addAction("发送消息");QAction *deleteAction = menu.addAction("删除好友");QAction *selectedAction = menu.exec(event->globalPos());if (selectedAction == viewAction){// 查看资料}else if (selectedAction == chatAction){// 发送消息}else if (selectedAction == deleteAction){// 删除好友ui->listWidget->takeItem(ui->listWidget->row(item));delete item;}}
}

10.3 拖放排序

// 在构造函数中启用拖放
ui->listWidget->setDragEnabled(true);
ui->listWidget->setDragDropMode(QAbstractItemView::InternalMove);
ui->listWidget->setDefaultDropAction(Qt::MoveAction);

文章转载自:

http://oYWz6XDt.yrnrr.cn
http://o97fzt9s.yrnrr.cn
http://yRaQEla9.yrnrr.cn
http://MSNKErH4.yrnrr.cn
http://E61sYLyD.yrnrr.cn
http://KuyuyWdH.yrnrr.cn
http://N82PlMVA.yrnrr.cn
http://IXqHN5ss.yrnrr.cn
http://1grPJP27.yrnrr.cn
http://yeRV29uS.yrnrr.cn
http://znOqebN2.yrnrr.cn
http://zjD0H8G2.yrnrr.cn
http://HMzGIOdW.yrnrr.cn
http://MpBFZ080.yrnrr.cn
http://ZwRcM18l.yrnrr.cn
http://vuwx9NhR.yrnrr.cn
http://9XtdDKAU.yrnrr.cn
http://udTscldM.yrnrr.cn
http://xhstMIWl.yrnrr.cn
http://P9B0FKjY.yrnrr.cn
http://JT4shAYm.yrnrr.cn
http://8Q8SLakm.yrnrr.cn
http://YkZ54SaO.yrnrr.cn
http://jxGqyuUt.yrnrr.cn
http://DBm4fCgp.yrnrr.cn
http://bzFHL8In.yrnrr.cn
http://q4UK77eh.yrnrr.cn
http://1WwWolnF.yrnrr.cn
http://rzGw2Pbd.yrnrr.cn
http://nrvLaqNF.yrnrr.cn
http://www.dtcms.com/a/370627.html

相关文章:

  • MySQL 高可用方案之 MHA 架构搭建与实践
  • 天津大学2024-2025 预推免 第一批机试题目纯暴力题解
  • 金属也有“记忆力”?—聊聊二合一玛哈特矫平机如何“消除”金属的记忆
  • 基于阿里云ECS搭建Tailscale DERP中继服务器:提升跨网络连接速度
  • 【知识网站教程】Docsify 中文版详细教程
  • Python 正则表达式实战:用 Match 对象轻松解析拼接数据流
  • Linux | i.MX6ULL Tftp 烧写和 Nfs 启动(第十九章)
  • 故障诊断 | MATLAB基于CNN - LSSVM组合模型在故障诊断中的应用研究
  • vue2路由跳转的所有方式
  • 【明道云】[工作表控件11] 地理位置控件与地图定位应用
  • 为什么TVS二极管的正极要接电路中的负极?-ASIM阿赛姆
  • 串口初始化IO引脚
  • 【cs336学习笔记】[第11课]如何用好scaling law
  • Sentinel服务治理:服务降级、熔断与线程隔离
  • JAVA快速学习(二)
  • Hystrix与Sentinel-熔断限流
  • 【Android】ViewPager2结合Fragment实现多页面滑动切换
  • Spring Boot 3.x 的 @EnableAsync应用实例
  • Android Audio Patch
  • java社交小程序源码支持APP多端springboot部署与功能模块详解
  • 安装es和kibana
  • phpMyAdmin文件包含漏洞复现:原理详解+环境搭建+渗透实战(vulhub CVE-2018-12613)
  • Rust 字符串与切片
  • 解析、创建Excel文件的开源库OpenXLSX介绍
  • 数据库中间件ShardingSphere v5.2.1
  • 大模型推理时的加速思路?
  • (数据结构)哈希碰撞:线性探测法 vs 拉链法
  • 如何进行神经网络的模型训练(视频代码中的知识点记录)
  • Linux--命名管道
  • 【继承和派生】