有时我们需要 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, [&](QString name){LF_favoriteList->item(name.toInt())->setSelected(true);});
connect(lineEdit, &NLineEdit::msnm_rls, this, [&](QString name){LF_favoriteList->item(name.toInt())->setSelected(true);});
connect(favora_logo, &NLabel::msnm_rls, this, [&](QString name){LF_favoriteList->item(name.toInt())->setSelected(true);});
connect(favora_rename, &NLabel::msnm_rls, this, [&](QString name){LF_favoriteList->item(name.toInt())->setSelected(true);favoraItemAction(1);});
connect(favora_remove, &NLabel::msnm_rls, this, [&](QString name){LF_favoriteList->item(name.toInt())->setSelected(true);favoraItemAction(0);});
RdoMap_Integer["Favora-item-addtion"] += 1;
}
如以上实例代码,我们添加了一个由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;
}
}
完成,以上仅仅是个示例,按这个思路写就行了