欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > QT 如何在 QListWidget 的选项中插入自定义组件

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

2024/10/25 7:28:34 来源:https://blog.csdn.net/qq_36500197/article/details/139389158  浏览:    关键词:QT 如何在 QListWidget 的选项中插入自定义组件

有时我们需要 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);
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com