Qt/C++ 开源控件 可折叠的标签管理控件

news/2024/11/18 0:07:58/

在 Qt 开发中,许多项目需要处理标签管理功能,例如分类管理、标签筛选等需求。本文将分享如何利用 Qt/C++ 实现一个具备动态增删标签、展开折叠功能的控件。此控件由 TagWindowTagItemWidget 两个类组成,前者负责整个标签管理窗口的布局与逻辑,后者表示单个标签项。文章将详细介绍控件实现的核心逻辑与思路。
在这里插入图片描述

设计思路

功能需求

  1. 标签项展示:显示带编号和颜色的标签项。
  2. 动态增删标签项:允许用户动态添加或删除标签项。
  3. 窗口展开折叠:控制标签窗口的展开与折叠,优化界面显示空间。

架构概述

  • TagWindow 类用于管理标签项的整体窗口布局,包括标签的列表显示、添加按钮、展开折叠按钮等。
  • TagItemWidget 类表示单个标签项,包含标签编号、可编辑的标签名称、删除按钮等。

接下来我们将从 TagWindowTagItemWidget 的具体实现入手,逐步解析各个模块的实现逻辑和思路。


TagItemWidget 类:实现单个标签项

TagItemWidget 代表单个标签项,包含标签的编号、名称和删除按钮。下面是 TagItemWidget.h 中的定义:

class TagItemWidget : public QWidget {Q_OBJECTpublic:TagItemWidget(int id, const QString &text, const QColor &color, QWidget *parent = nullptr);QString getText() const;         ///< 获取标签的文本内容void setText(const QString &text); ///< 设置标签的文本内容void enableEditing(bool enable); ///< 控制标签名称是否可编辑signals:void requestDeletion(TagItemWidget *item); ///< 请求删除该标签项的信号protected:bool eventFilter(QObject *obj, QEvent *event) override; ///< 事件过滤器用于双击进入编辑模式private:QLabel *idLabel;        ///< 显示标签编号QLineEdit *nameEdit;    ///< 标签名称编辑框QPushButton *deleteButton; ///< 删除按钮
};

构造函数解析

构造函数的主要任务是初始化各组件,并实现标签编号的圆角背景色效果。以下是构造函数的实现:

TagItemWidget::TagItemWidget(int id, const QString &text, const QColor &color, QWidget *parent): QWidget(parent) {QHBoxLayout *layout = new QHBoxLayout(this);// 标签编号idLabel = new QLabel(QString::number(id), this);idLabel->setFixedSize(20, 20);idLabel->setAlignment(Qt::AlignCenter);idLabel->setStyleSheet("background-color: " + color.name() + "; border-radius: 10px; color: white;");// 标签名称编辑框nameEdit = new QLineEdit(text, this);nameEdit->setReadOnly(true); // 默认不可编辑// 删除按钮deleteButton = new QPushButton("删除", this);deleteButton->setFixedSize(40, 20);connect(deleteButton, &QPushButton::clicked, this, [this]() {emit requestDeletion(this);});layout->addWidget(idLabel);layout->addWidget(nameEdit);layout->addWidget(deleteButton);layout->addStretch();// 双击进入编辑模式connect(nameEdit, &QLineEdit::editingFinished, this, [this]() {nameEdit->setReadOnly(true);});nameEdit->installEventFilter(this);
}

事件过滤器

为了实现双击标签名称进入编辑模式,TagItemWidget 类重写了 eventFilter 方法:

bool TagItemWidget::eventFilter(QObject *obj, QEvent *event) {if (obj == nameEdit && event->type() == QEvent::MouseButtonDblClick) {enableEditing(true);return true;}return QWidget::eventFilter(obj, event);
}

该方法会在检测到双击事件时调用 enableEditing,使标签名称进入可编辑状态。


TagWindow 类:实现标签管理窗口

TagWindow 类负责管理多个标签项,包括标签项的添加、删除、窗口的展开和折叠等功能。以下是 TagWindow.h 中的定义:

class TagWindow : public QWidget {Q_OBJECTpublic:explicit TagWindow(QWidget *parent = nullptr);private slots:void toggleExpandCollapse();    ///< 控制窗口的展开/折叠void addItem();                 ///< 添加标签项void deleteItem(TagItemWidget *item); ///< 删除指定的标签项void adjustListWidgetHeight();  ///< 调整 listWidget 的高度private:QVBoxLayout *mainLayout;        ///< 主布局QPushButton *expandCollapseButton; ///< 展开/折叠按钮QPushButton *addButton;         ///< 添加按钮QListWidget *listWidget;        ///< 标签列表QPropertyAnimation *animation;  ///< 控制展开/折叠的动画int collapsedHeight;            ///< 折叠时的高度QString getRandomText();        ///< 生成随机文本QColor getRandomColor();        ///< 生成随机颜色
};

初始化布局

TagWindow 的构造函数实现了控件的初始化和布局:

TagWindow::TagWindow(QWidget *parent) : QWidget(parent) {mainLayout = new QVBoxLayout(this);mainLayout->setContentsMargins(0, 0, 0, 0);// 标题和展开/折叠按钮QHBoxLayout *headerLayout = new QHBoxLayout();QLabel *titleLabel = new QLabel(tc("标签类别:"));expandCollapseButton = new QPushButton("+");connect(expandCollapseButton, &QPushButton::clicked, this, &TagWindow::toggleExpandCollapse);headerLayout->addWidget(titleLabel);headerLayout->addWidget(expandCollapseButton);mainLayout->addLayout(headerLayout);// 添加按钮addButton = new QPushButton("+");connect(addButton, &QPushButton::clicked, this, &TagWindow::addItem);mainLayout->addWidget(addButton);// 标签列表listWidget = new QListWidget(this);listWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);listWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);listWidget->setVisible(false);mainLayout->addWidget(listWidget);// 折叠高度collapsedHeight = addButton->sizeHint().height() + expandCollapseButton->sizeHint().height();animation = new QPropertyAnimation(this, "maximumHeight");animation->setDuration(300);setFixedHeight(collapsedHeight);
}

添加与删除标签项

用户点击添加按钮会调用 addItem,随机生成标签内容和颜色,创建新标签项并添加到 listWidget 中:

void TagWindow::addItem() {QColor color = getRandomColor();QString randomText = getRandomText();TagItemWidget *itemWidget = new TagItemWidget(listWidget->count() + 1, randomText, color);QListWidgetItem *listItem = new QListWidgetItem(listWidget);listItem->setSizeHint(itemWidget->sizeHint());listWidget->setItemWidget(listItem, itemWidget);connect(itemWidget, &TagItemWidget::requestDeletion, this, &TagWindow::deleteItem);listWidget->setVisible(true);adjustListWidgetHeight();
}

删除标签项时通过 deleteItem 实现:

void TagWindow::deleteItem(TagItemWidget *item) {for (int i = 0; i < listWidget->count(); ++i) {QListWidgetItem *listItem = listWidget->item(i);if (listWidget->itemWidget(listItem) == item) {delete listWidget->takeItem(i);break;}}if (listWidget->count() == 0) {listWidget->setVisible(false);}adjustListWidgetHeight();
}

控制窗口的展开和折叠

点击展开/折叠按钮会触发 toggleExpandCollapse 方法,通过动画效果平滑展开或折叠窗口:

void TagWindow::toggleExpandCollapse() {if (listWidget->count() == 0) return;bool isExpanded = !listWidget->isVisible();int targetHeight = isExpanded ? (collapsedHeight + listWidget->sizeHint().height()) : collapsedHeight;animation->stop();animation->setStartValue(height());animation->setEndValue(targetHeight);animation->start();expandCollapseButton->setText(isExpanded ? "-" : "+");connect(animation, &QPropertyAnimation::finished, this, [=]() {setFixedHeight(targetHeight);listWidget->setVisible(isExpanded);});adjustListWidgetHeight();
}

总结

本文介绍了一个基于 Qt 的标签管理控件的实现,包括标签项的创建、删除和窗口的展开折叠效果。通过对 TagWindowTagItemWidget 的详细讲解,相信大家能更好地理解如何设计和实现一个可复用的 Qt 控件。在实际开发中,您可以根据需求对控件功能进行扩展,如增加多标签选择、标签项排序等功能。希望本文能为您在 Qt 开发中的自定义控件设计提供参考。


http://www.ppmy.cn/news/1547839.html

相关文章

git配置用户信息

在 Git 中配置用户信息&#xff0c;主要是设置你的用户名和电子邮件地址&#xff0c;这些信息会被 Git 用来记录提交的作者信息。以下是配置用户信息的步骤&#xff1a; 打开命令行工具。 设置你的用户名&#xff1a; git config --global user.name "你的名字"例如…

onlyoffice Command service(命令服务)使用示例

一、说明 文档在这里&#xff1a;https://api.onlyoffice.com/docs/docs-api/additional-api/command-service/ 命令服务提供有几个简单的接口封装。也提供了前端和后端同时操作文档的可能。 二、正文 命令服务地址&#xff1a;https://documentserver/coauthoring/Com…

【再谈设计模式】抽象工厂模式~对象创建的统筹者

一、引言 在软件开发的世界里&#xff0c;高效、灵活且易于维护的代码结构是每个开发者追求的目标。设计模式就像是建筑蓝图中的经典方案&#xff0c;为我们提供了应对各种常见问题的有效策略。其中&#xff0c;抽象工厂模式在对象创建方面扮演着重要的角色&#xff0c;它如同一…

Linux系统制作Java JAR程序为系统服务

在Linux系统中&#xff0c;将JAR程序制作成系统服务可以通过系统自带的systemd服务管理器来实现。systemd是现代Linux系统中广泛使用的初始化系统和服务管理器&#xff0c;它提供了强大的功能来管理系统的启动和服务。 以下是将JAR程序制作成systemd系统服务的步骤&#xff0c…

2024-11-16 特殊矩阵的压缩存储

一、数组的存储结构 1.一维数组&#xff1a;各元素大小相同&#xff0c;且物理上连续存放。a[i]起始地址i*siezof(数组元素大小) 2.二维数组&#xff1a;b[j][j]起始地址&#xff08;i*Nj&#xff09;*sizeof(数组元素大小) 二、特殊矩阵 1.普通矩阵的存储&#xff1a;使用…

酷炫的鼠标移入效果(附源码!!)

预览效果 源码(htmljs部分) <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title>…

对称加密算法DES的实现

一、实验目的 1、了解对称密码体制基本原理 2、掌握编程语言实现对称加密、解密 二、实验原理 DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位&#xff0c;产生最大 64 位的分组大小。这是一个迭代的分组密码&#xff0c;使用称为 Feistel 的技术&#xff0c;其中将加密…

基于机器学习的虚拟传感器用于门开启检测和异常检测

论文标题&#xff1a;Virtual sensor for door opening detection and anomaly detection using machine learning&#xff08;基于机器学习的虚拟传感器用于门开启检测和异常检测&#xff09; 作者信息&#xff1a; Almir Neto&#xff0c;来自巴西马拉尼昂联邦教育、科学与…