QT 如何在 QListWidget 的选项中插入自定义组件

news2024/11/16 18:32:25

有时我们需要 QListWidget  完成更复杂的操作,而不仅限于添加文本或者图标,那么就会使用到 setItemWidget 函数,但是这也会伴生一个问题,插入自定义组件后,QListWidget  对选项点击事件的获取会收到阻塞,因为点击会有概率落到我们的自定义组件上,这时候我们可以这样解决该问题:

方案1:

组件1 *1 = new 组件1(组件有点击信号)
组件2 *2 = new 组件2(组件有点击信号)
QListWidgetItem *temporary_item1 = new QListWidgetItem();
QListWidgetItem *temporary_item2 = new QListWidgetItem();
QListWidget->addItem(temporary_item);
QListWidget->setItemWidget(temporary_item1, 1);
QListWidget->addItem(temporary_item2);
QListWidget->setItemWidget(temporary_item2, 2);
connect(1, &组件1::点击信号, this, [&](){LF_favoriteList->item(1)->setSelected(true);});
connect(2, &组件2::点击信号, this, [&](){LF_favoriteList->item(2)->setSelected(true);});

这样我们就可以通过组件的点击信号来手动触发 QListWidget 的点击事件,选中选项,但是问题也很明显,如果选项非静态的话呢?静态的情况下麻烦一点一个一个写好放进去就ok了,动态的话行不通,这就使用到方案2了

方案2(推荐->适用更复杂的自定义组件):

void MediaLogicGO::favoraListLoad(QString text, QString logo_path){
    Nwidget *temporary = new Nwidget();
    temporary->setAttribute(Qt::WA_DeleteOnClose);
    QHBoxLayout *temHbox = new QHBoxLayout(temporary);
    NLabel * favora_logo = new NLabel(temporary);
    NLineEdit *lineEdit = new NLineEdit(temporary);
    NLabel *favora_rename = new NLabel(temporary);
    NLabel *favora_remove = new NLabel(temporary);
    favora_rename->setSyncEnable(true);
    favora_remove->setSyncEnable(true);
    favora_logo->setSyncEnable(true);
    favora_logo->setFixedHeight(23);
    favora_rename->setFixedHeight(23);
    favora_remove->setFixedHeight(23);
    favora_logo->setAdjustFixedWidth(true);
    favora_rename->setAdjustFixedWidth(true);
    favora_remove->setAdjustFixedWidth(true);
    favora_rename->setdrawType(NT::DRAWTYPE_ROUND);
    favora_remove->setdrawType(NT::DRAWTYPE_ROUND);
    favora_rename->setSyncPixdrawType(NT::DRAWTYPE_RECT, 3);
    favora_remove->setSyncPixdrawType(NT::DRAWTYPE_RECT, 3);
    favora_rename->setSyncBackColorOption({{WIN_MOUSE_ATTRIBUTE.WIN_ENTER, QColor(255,255,255,230)}});
    favora_remove->setSyncBackColorOption({{WIN_MOUSE_ATTRIBUTE.WIN_ENTER, QColor(255,255,255,230)}});
    favora_logo->setPixmapC(logo_path);
    favora_rename->setPixmapC(":/PIXMAP/bench/private-rename.png");
    favora_remove->setPixmapC(":/PIXMAP/bench/private-remove.png");
    lineEdit->setStyleSheet("QLineEdit{background:transparent; border:0px; color:rgba(89,89,89,200); font:12px;}");
    lineEdit->setReadOnly(true);
    lineEdit->setText(text);
    temHbox->addWidget(favora_logo);
    temHbox->addWidget(lineEdit);
    temHbox->addWidget(favora_rename);
    temHbox->addWidget(favora_remove);
    temHbox->setAlignment(Qt::AlignVCenter);
    temHbox->setContentsMargins(0,0,0,0);
    temHbox->setSpacing(0);
    QListWidgetItem *temporary_item = new QListWidgetItem();
    LF_favoriteList->addItem(temporary_item);
    LF_favoriteList->setItemWidget(temporary_item, temporary);
    temporary->setObjectName(QString::number(RdoMap_Integer["Favora-item-addtion"]));
    lineEdit->setObjectName(QString::number(RdoMap_Integer["Favora-item-addtion"]));
    favora_logo->setObjectName(QString::number(RdoMap_Integer["Favora-item-addtion"]));
    favora_rename->setObjectName(QString::number(RdoMap_Integer["Favora-item-addtion"]));
    favora_remove->setObjectName(QString::number(RdoMap_Integer["Favora-item-addtion"]));
    connect(temporary, &Nwidget::msnm_rls, this, &MediaLogicGO::favora_selection);
    connect(lineEdit, &NLineEdit::msnm_rls, this, &MediaLogicGO::favora_selection);
    connect(favora_logo, &NLabel::msnm_rls, this, &MediaLogicGO::favora_selection);
    connect(favora_rename, &NLabel::msnm_rls, this, [&](QString name){favora_selection(name);favoraItemAction(1);});
    RdoMap_Integer["Favora-item-addtion"] += 1;
}

void MediaLogicGO::favora_selection(QString name){
    QListWidgetItem *currantItem = Favora_ListWidget->item(name.toInt());

    if (currantItem != NULL) currantItem->setSelected(true);
}

如以上实例代码,我们添加了一个由logo图标,文本框,两个操作按钮的自定义组件,并给他们做了信号连接,正常情况下,QListWidget 选项会被自定义组件遮挡一部分,非遮挡部分正常点击选中

 例如左图这个情况,大概率是全部遮挡了,那么为了解决这个问题,我们把自定义组件、以及组件中的文本框、logo、重命名和删除组件 的点击事件做一个信号连接,把对象名称传出来,对象名称我们就设置该组件的行数,以此手动触发选项的选中事件,其中重命名按钮和删除按钮触发选项的选中还触发该组件的点击,目的是为了避免已经操作了按钮但是选项并没有选中的尴尬情况

效果:

既然触发了选项的点击,那就好办了,使用 QListWidget 的 itemSelectionChanged 信号获取选中数据,这里我获取文本框的文本,也可以获取 QListWidgetItem 或者 选中的行,对应操作需要什么数据就获取什么

void MediaLogicCT::priLiswItemChange(/*QListWidgetItem *Item*/){
    QList<QListWidgetItem*> items = LF_favoriteList->selectedItems();
    QList<QString> texts;
    foreach(QListWidgetItem *item, items)
    {
        int item_row = LF_favoriteList->row(item);
        NLineEdit *edit = LF_favoriteList->itemWidget(item)->findChild<NLineEdit*>(QString::number(item_row));
        QString text = edit->text();
        texts.append(text);
    }

    qDebug() << "当前选项" << texts.last();
    qDebug() << "所选选项" << texts;
    RdoMap_String["list-text"] = texts.last();
}


下面是操作按钮对应的函数
void MediaLogicGO::favoraItemAction(int Type){
    switch (Type) {
        case 0:
            qDebug() << RdoMap_String["list-text"] << "选项即将删除";
            在这里编写删除的逻辑代码
            break;
        case 1:
            qDebug() << RdoMap_String["list-text"] << "选项即将重命名";
            在这里编写删除的逻辑代码
            break;
    }  
}

完成,以上仅仅是个示例,按这个思路写就行了

好吧,这个情况与仅仅添加QListWidgetItem不同,当删除选项时必须得先删除选项绑定的 自定义组件,因为自定义组件是绑定在 Item 上的,不这么做会导致系统崩溃,下面补充下删除的思路

删除方案1:   全部清除再重新添加

优点:  比较安全稳定

缺点:  数据大的时候,如几百上千条的时候,就卡了,得放线程里跑

int favora_size = Favora_ListWidget->count(); //数据总行数
int row = 0; //行数
int expectrow = 0; //首行
while (row < favora_size) //小于总行数的情况下,行数累加
{
	QListWidgetItem *current_item = Favora_ListWidget->item(expectrow); //获取第一个选项
	QWidget *itemWidget = Favora_ListWidget->itemWidget(current_item); //获取对应自定义组件
	if (itemWidget) //如果有自定义组件
	{
		Favora_ListWidget->removeItemWidget(current_item);
		delete itemWidget;  //删掉
	}
	if (current_item != NULL) //如果选项不为空(有效)
	{
		delete Favora_ListWidget->takeItem(expectrow); 删掉
	}
	row++;
}
//这是测试数据,我们对应把测试数据的需要删除的项也给删了
RdoMap_ListStr["ttt"].removeAt(RdoMap_Integer["list-row"]); 
foreach(QString text, RdoMap_ListStr["ttt"]) //重新加载数据
{
	favoraListLoad(text, ":/PIXMAP/bench/private-logo.png");
}

删除方案2: 单个删除

优点: 不用大动干戈的做删除添加

缺点:  删除掉某个数据之后,这个数据之后的选项,选中时点击的选项和选中不一致,因为索引往 前掉一位了,也就是说后面的这些选项,本来索引是 6的,前面的数据删了一个,索引应该改为5才能正常对应上,但是我们的索引在添加数据时写入作为对象名称了,你改的话还得后面的元素全部改,再者貌似选项没有选中时,还获取不到 Item里面的自定义组件。

*****所以,我们需要创建一个列表,用于维护索引改变的情况,已删除的项在列表里置为false状态,当选定 10 索引的选项时,判断下 10 索引之前的选项有几个是状态为false的,将索引减去为false的数据总和,即可得出正确的索引,选的到正确的索引,其他的也步入正轨了,对象名称仅仅是这个作用而已

如我们有 10个选项,已经删了3个,选中第8个,

    QList<bool> stateList({true, true, true, true, true, true, true, true, true, true});
    //1、3、5 已删除
    stateList[1] = false;
    stateList[3] = false;
    stateList[5] = false;
    //选中索引8的选项 ************************************
    int count = 0;
    foreach(bool state, stateList.mid(0, 8)) if (!state) count++;
    qDebug() << "当前正确的选项" << 8 - count;

我们只用在 favora_selection 函数加上 星号之后的代码,星号之前的除了已定义好的列表,将选项置为False的操作在删除 Item时已经做了。删除的代码改为针对单个选项就即可, 后面再补充 stateList 对应 expectrow 的项置为false就行了

int expectrow = RdoMap_Integer["list-row"];
QListWidgetItem *current_item = Favora_ListWidget->item(expectrow);
QWidget *itemWidget = Favora_ListWidget->itemWidget(current_item);
if (itemWidget)
{
	Favora_ListWidget->removeItemWidget(current_item);
	delete itemWidget;
}
if (current_item != NULL)
{
	delete Favora_ListWidget->takeItem(expectrow);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1800165.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ESP使用巴法云远程OTA(VScode + Platform io)

ESP使用巴法云远程OTA&#xff08;Platform&#xff09; 什么是OTA&#xff1a; OTA&#xff08;Over-the-AirTechnology&#xff09;即空中下载技术&#xff0c;是通过移动通信的空中接口实现对移动终端设备及SIM卡数据进行远程管理的技术。OTA升级是物联网&#xff08;IOT&am…

关于RDMA传输的基本流量控制

Basic flow control for RDMA transfers | The Geek in the Corner (wordpress.com) 文心一言 已经介绍了使用发送/接收操作和RDMA读写操作&#xff0c;那么现在是一个很好的机会来结合这两种方法的元素&#xff0c;并讨论一般的流量控制。还会稍微谈谈RDMA带有立即数据的写操…

外部mysql导入

利用这个命令&#xff1a; mysql -u username -p database_name < file.sql 然后就这样。成功导入。

惠海 H5528 升降压芯片 12V24V36V48V60V75V LED恒流驱动IC 调光细腻顺滑无阶梯感

惠海H5528是一款升压、降压、升压降压的LED恒流驱动IC&#xff0c;其具备宽范围调光比且无频闪调光的特性&#xff0c;使得它在智能照明、Dali调光、0~10V调光、摄影灯照明以及补光灯照明等多种应用中具有广泛的应用前景。 这款芯片支持降压、升压和升降压拓扑的应用&#xff0…

torch.cat 与 torch.concat函数

文章目录 区别torch.cat介绍作用参数使用实例关于参数dim为None的使用 区别 先说结论&#xff1a;没有区别在功能、用法以及作用上&#xff0c;concat函数就是cat函数的别名&#xff08;官方就是这样说的&#xff09;。下面截图为证&#xff1a;   因此接下来就主要是介绍 to…

艾体宝方案 | ntopng监测异常流量并通知到企业微信

你是否曾因网络异常而感到困扰&#xff1f;在数字化时代&#xff0c;网络流量异常可能给企业带来巨大损失。但别担心&#xff0c;我们为您准备了一份详尽的解决方案&#xff01;想知道如何利用ntopng及时发现异常流量&#xff0c;并通过企业微信等渠道通知你的团队吗&#xff1…

【Qt秘籍】[007]-LineEdit Pushbutton控件

Qt的中有着各种各样的控件&#xff0c;相较于传统C/C的输出默认只能在控制台实现&#xff0c;Qt中可以有不同的接口实现各种不同的功能&#xff0c;下面我们将实现不同功能的输出 hello world&#xff01; 标签Label 【Qt秘籍】[006]-Label实现Hello World程序-编程第一步-CSD…

C#操作MySQL从入门到精通(13)——对查询结果使用函数

前言 我们有时候需要对查询到的数据使用函数进行处理,比如去掉空格,比如截取一半长度等操作,下面我来详细介绍: 本文使用的测试数据如下: 1、使用文本处理函数 1.1 Left 返回具有指定长度的字符串的左边部分 下面的代码获取email这个列从左边第一个字符开始计算的一共…

使用 ISIC 快速申请 JetBrain 学生免费产品

此篇文章适合急需通过学生优惠使用 JetBrain 产品并且愿意花费 50 &#xff08;申请国际电子学生证 ISIC 需要 50&#xff09;的学生。需要等待时间1-3天&#xff0c;主要是等待 ISIC 的时间&#xff0c;只要 ISIC 发放 ISIC name 和 ISIC ID&#xff0c;将其填写到 JetBrain 的…

Linux学习笔记8

介绍man命令 在Linux中&#xff0c;man命令用于查看系统手册页&#xff08;manual pages&#xff09;。系统手册页是关于各种Linux命令、函数库以及系统调用的详尽文档&#xff0c;能够提供关于命令的使用方法、参数说明、示例以及其他相关信息 可以利用man xxx的命令去查找某…

系统架构设计师【第19章】: 大数据架构设计理论与实践 (核心总结)

文章目录 19.1 传统数据处理系统存在的问题19.2 大数据处理系统架构分析19.2.1 大数据处理系统面临挑战19.2.2 大数据处理系统架构特征 19.3 Lambda架构19.3.1 Lambda架构对大数据处理系统的理解19.3.2 Lambda架构应用场景19.3.3 Lambda架构介绍19.3.4  Lambda架构的实…

MySQL(四) - SQL优化

一、SQL执行流程 MySQL是客户端-服务器的模式。一条SQL的执行流程如下&#xff1a; 在执行过程中&#xff0c;主要有三类角色&#xff1a;客户端、服务器、存储引擎。 大致可以分为三层&#xff1a; 第一层&#xff1a;客户端连接到服务器&#xff0c;构造SQL并发送给服务器…

电源变压器的作用和性能

电源变压器的主要作用是改变输入电压的大小&#xff0c;通常用于降低电压或升高电压&#xff0c;以便适应不同设备的需求。它们还可以提供隔离&#xff0c;使得输出电路与输入电路之间电气隔离&#xff0c;从而提高安全性。性能方面&#xff0c;电源变压器需要具有高效率、低温…

【OpenHarmony】ArkTS 语法基础 ④ ( ArkTS UI 渲染控制 | if else 条件渲染 | ForEach 循环渲染 )

文章目录 一、ArkTS UI 渲染控制1、if else 条件渲染2、ForEach 循环渲染 二、完整代码示例1、自定义组件代码2、主界面代码3、执行结果 参考文档 : <HarmonyOS第一课>ArkTS开发语言介绍 ForEach 渲染控制文档 : https://developer.huawei.com/consumer/cn/doc/harmonyo…

Python中的Paramiko与FTP文件夹及文件检测技巧

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; Python代码的魅力与实用价值 在当今数字化时代&#xff0c;编程已成为一种不可或缺的技能。Python作为一种简洁、易读且功能强大的编程语言&#xff0c;受到了全球开发者的喜爱。它不仅适用于初学者入门&#xff0c…

玩转STM32-通信协议SPI(详细-慢工出细活)

文章目录 一、SPI的基础知识1.1 接口定义1.2 单机和多机通信 二、STM32的SPI工作过程2.1 从选择&#xff08;NSS&#xff09;脚管理2.2 时钟相位与极性2.3 SPI主模式2.4 SPI从模式 三、应用实例 一、SPI的基础知识 1.1 接口定义 SPI系统可直接与各个厂家生产的多种标准外围器…

通俗易懂的解释保护性看跌期权和抛补看涨期权!

今天带你了解通俗易懂的解释保护性看跌期权和抛补看涨期权&#xff01;当涉及期权交易时&#xff0c;保护性看跌期权和抛补看涨期权是两种常见的策略&#xff0c;它们的目的都是为了在特定市场情况下对投资进行保护或增强收益。 保护性看跌期权 保护性看跌期权是一种风险管理策…

如何以非交互方式将参数传递给交互式脚本

文章目录 问题回答1. 使用 Here Document2. 使用 echo 管道传递3. 使用文件描述符4. 使用 expect 工具 参考 问题 我有一个 Bash 脚本&#xff0c;它使用 read 命令以交互方式读取命令参数&#xff0c;例如 yes/no 选项。是否有一种方法可以在非交互式脚本中调用这个脚本&…

粘性代理 vs 轮换代理: 特点、优势与选择指南

在网络领域&#xff0c;代理服务器是一种常见的工具&#xff0c;用于隐藏真实IP地址并提供更安全和匿名的网络体验。 粘性代理和轮换代理是两种常见的代理类型&#xff0c;它们在IP持久性和变更频率等方面有所不同。 本文将介绍粘性代理和轮换代理的区别&#xff0c;并分析在…

1.Linux入门

文章目录 一、介绍1.1 操作系统1.2 Linux1.3 虚拟机1.4 安装 CentOS7 二、远程连接 Linux2.1 FinalShell2.2 远程连接Linux 三、扩展3.1 WSL3.2 虚拟机快照 一、介绍 1.1 操作系统 我们平常所用的电脑是个人桌面操作系统&#xff0c;也就是Windows或者是macOS 目前我们要学的…