自定义多选QComboBox

因项目需求,需要实现QComboBox的多选功能,如下图所示:

思路:QListWidget + QListWidgetItem + QCheckBox

代码如下

#ifndef MUTICOMBOBOX_H
#define MUTICOMBOBOX_H

#include <QWidget>
#include <QListWidget>
#include <QLineEdit>
#include <QComboBox>


class  MutiComboBox : public QComboBox
{
	Q_OBJECT

public:
	MutiComboBox(QWidget *parent = 0);
	MutiComboBox(const QMap<int,QString> &mapData,QWidget *parent = 0);
	~MutiComboBox();

public:
	void setModelData(const QMap<int,QString> &mapData);
	void setCheckedItems(const QString &data);
	QString getSelectedItemDatas();


private slots:
	void stateChanged(int state);
	void textChanged(const QString &text);

private:
	void clear();

private:
	QListWidget *pListWidget;
	QLineEdit *pLineEdit;
	QString strSelectedText;
	bool bSelected;
};

#endif // MUTICOMBOBOX_H

具体实现:

#include "muticombobox.h"

#include <QCheckBox>
#include <QDebug>


MutiComboBox::MutiComboBox(QWidget *parent)
	: QComboBox(parent)
{
	pListWidget = new QListWidget(this);
	pListWidget->setObjectName("MutiComboBoxListWidget");
	pLineEdit = new QLineEdit(this);
	//this->setModel(pListWidget->model());
	//this->setView(pListWidget);
	this->setLineEdit(pLineEdit);
	pLineEdit->setReadOnly(true);
	connect(pLineEdit,SIGNAL(textChanged(const QString &)),this,SLOT(textChanged(const QString &)));
}

MutiComboBox::MutiComboBox(const QMap<int,QString> &mapData,QWidget *parent)
:QComboBox(parent)
{
	pListWidget = new QListWidget(this);
	pLineEdit = new QLineEdit(this);
	QMapIterator<int,QString> it(mapData);
	while(it.hasNext()){
		it.next();
		QListWidgetItem *pItem = new QListWidgetItem(pListWidget);
		pListWidget->addItem(pItem);
		pItem->setData(Qt::UserRole,it.key());
		QCheckBox *pCheckBox = new QCheckBox(this);
		pCheckBox->setText(it.value());
		pListWidget->addItem(pItem);
		pListWidget->setItemWidget(pItem,pCheckBox);
		connect(pCheckBox,SIGNAL(stateChanged(int)),this,SLOT(stateChanged(int)));
	}

	this->setModel(pListWidget->model());
	this->setView(pListWidget);
	this->setLineEdit(pLineEdit);
	pLineEdit->setReadOnly(true);
	connect(pLineEdit,SIGNAL(textChanged(const QString &)),this,SLOT(textChanged(const QString &)));
}

MutiComboBox::~MutiComboBox()
{
	delete pListWidget;
	delete pLineEdit;
}
void MutiComboBox::setModelData(const QMap<int,QString> &mapData)
{
	int count = pListWidget->count();
	for (int row = 0; row < count;++row)
	{
		QListWidgetItem *pItem = pListWidget->takeItem(0);
		delete pItem;
	}
	
	QMapIterator<int,QString> it(mapData);
	while(it.hasNext()){
		it.next();
		QListWidgetItem *pItem = new QListWidgetItem(pListWidget);
		pListWidget->addItem(pItem);
		pItem->setData(Qt::UserRole,it.key());
		QCheckBox *pCheckBox = new QCheckBox(this);
		pCheckBox->setText(it.value());
		pListWidget->addItem(pItem);
		pListWidget->setItemWidget(pItem,pCheckBox);
		connect(pCheckBox,SIGNAL(stateChanged(int)),this,SLOT(stateChanged(int)));
	}
	this->setModel(pListWidget->model());
	this->setView(pListWidget);
}

void MutiComboBox::setCheckedItems(const QString &data)
{
	clear();

	if(data.isEmpty())
		return;

	int count = pListWidget->count();
	QStringList list(data.split(";"));
	QStringListIterator it(list);
	while(it.hasNext())
	{
		QString da = it.next();
		for(int i=0;i<count;++i)
		{
			QListWidgetItem *pItem = pListWidget->item(i);
			if(pItem->data(Qt::UserRole).toString() == da)
			{
				QWidget *pWidget = pListWidget->itemWidget(pItem);
				QCheckBox *pCheckBox = (QCheckBox*) pWidget;
				pCheckBox->setChecked(true);
				break;
			}
		}
	}
}
QString MutiComboBox::getSelectedItemDatas()
{
	int nCount = pListWidget->count();
	QString strSeltectedData("");
	for(int i=0; i < nCount; ++i)
	{
		QListWidgetItem *pItem = pListWidget->item(i);
		QWidget *pWidget = pListWidget->itemWidget(pItem);
		QCheckBox *pCheckBox = (QCheckBox*) pWidget;
		if(pCheckBox->isChecked()){
			QString strText = pItem->data(Qt::UserRole).toString().trimmed();
			strSeltectedData.append(strText).append(";");
		}
	}

	if(strSeltectedData.endsWith(";"))
	{
		strSeltectedData.remove(strSeltectedData.count()-1,1);
	}
	return strSeltectedData;
}


void MutiComboBox::stateChanged(int state)
{
	bSelected = true;
	QString strSelectedData("");
	strSelectedText.clear();
	QObject *object= QObject::sender();
	QCheckBox *pSenderCheckBox = static_cast<QCheckBox*>(object);
	int nCount = pListWidget->count();
	for(int i=0; i < nCount; ++i)
	{
		QListWidgetItem *pItem = pListWidget->item(i);
		QWidget *pWidget = pListWidget->itemWidget(pItem);
		QCheckBox *pCheckBox = (QCheckBox*) pWidget;
		if(pCheckBox->isChecked()){
			QString strText = pCheckBox->text();
			strSelectedData.append(strText).append(";");
		}
	}

	if(strSelectedData.endsWith(";"))
	{
		strSelectedData.remove(strSelectedData.count()-1,1);
	}

	if(!strSelectedData.isEmpty())
	{
		strSelectedText = strSelectedData;
		pLineEdit->setText(strSelectedData);
		pLineEdit->setToolTip(strSelectedData);
	}else{
		pLineEdit->clear();
	}
	bSelected = false;
}

void MutiComboBox::textChanged(const QString &text)
{
	if(!bSelected)
	{
		pLineEdit->setText(strSelectedText);
	}
}

void MutiComboBox::clear(){
	int nCount = pListWidget->count();
	for(int i=0; i < nCount; ++i)
	{
		QListWidgetItem *pItem = pListWidget->item(i);
		QWidget *pWidget = pListWidget->itemWidget(pItem);
		QCheckBox *pCheckBox = (QCheckBox*) pWidget;
		if(pCheckBox->isChecked()){
			pCheckBox->setChecked(false);
		}
	}
	strSelectedText = "";
	pLineEdit->setText("");
}

使用方法:

1.在Qt designer中的UI先添加 QComboBox控件,然后提升该控件为自定义的控件 MutiComboBox

2.通过setModelData的方式,将列表中的数据传给MutiComboBox

如:

    ui->cmbRes->setModelData(m_LogictActIDMap);

 

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是使用自定义 QComboBox 实现多选功能的示例代码: ```python import sys from PyQt5.QtCore import Qt, QRect from PyQt5.QtGui import QPainter from PyQt5.QtWidgets import QApplication, QComboBox class MultiSelectComboBox(QComboBox): def __init__(self, parent=None): super(MultiSelectComboBox, self).__init__(parent) self.setInsertPolicy(QComboBox.NoInsert) # 禁止用户手动输入 self.is_multi_select = False # 多选标志 self.selected_items = set() # 存储已选项的集合 def mousePressEvent(self, event): if event.button() == Qt.LeftButton: if self.is_multi_select: self.is_multi_select = False else: self.is_multi_select = True self.showPopup() # 显示下拉选项 def paintEvent(self, event): painter = QPainter(self) option = self.view().itemDelegate().styleOptionViewItem() # 绘制已选项的背景色 for index in range(self.model().rowCount()): if index in self.selected_items: option.rect = self.view().visualRect(index) painter.save() painter.fillRect(option.rect, option.palette.highlight()) painter.restore() # 绘制文本 self.view().itemDelegate().paint(painter, option, QModelIndex()) def hidePopup(self): if not self.is_multi_select: super(MultiSelectComboBox, self).hidePopup() def addItem(self, text): super(MultiSelectComboBox, self).addItem(text) def itemSelected(self, index): if self.is_multi_select: if index in self.selected_items: self.selected_items.remove(index) else: self.selected_items.add(index) else: self.selected_items.clear() self.selected_items.add(index) self.update() if __name__ == '__main__': app = QApplication(sys.argv) combo = MultiSelectComboBox() combo.addItem("Option 1") combo.addItem("Option 2") combo.addItem("Option 3") combo.show() sys.exit(app.exec_()) ``` 在上述代码中,我们创建了一个名为 `MultiSelectComboBox` 的自定义多选下拉框类。在该类中,我们重写了 `mousePressEvent` 方法来切换多选标志,并在多选状态下显示下拉选项。我们还重写了 `paintEvent` 方法来自定义绘制已选项的样式。通过 `selected_items` 集合来存储已选项的索引。 运行上述代码,你将看到一个具有多选功能的下拉框。当你点击下拉按钮时,切换到多选状态,再次点击则切换回单选状态。在多选状态下,你可以点击并选择多个选项,已选项会以不同的背景色进行区分。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值