本文记录了一种通过继承 QComboBox 实现下拉列表多选功能的方法。效果如下图所示:

普通的下拉列表只支持选择一个选项,在软件开发过程中,经常会遇到下拉列表支持选择多个选项的需求,下面的代码实现了下拉列表多选功能,支持设置弹窗的高度,支持添加显示文本和用户数据,支持设置默认选中项目,支持获取选中数据。
#ifndef LLCOMBOBOX_H
#define LLCOMBOBOX_H
#include
class QListWidgetItem;
class LLComboBoxPrivate;
class LLComboBox : public QComboBox
{
Q_OBJECT
public:
explicit LLComboBox(QWidget* parent = NULL);
/**
* @brief addDataItem 添加数据
* @param text
* @param userData
*/
void addDataItem(const QString &text, const QVariant &userData = QVariant());
/**
* @brief setSelectedData 设置选中的数据
* @param selectedData
*/
void setSelectedData(const QStringList &selectedData);
/**
* @brief setPopupViewHeight 设置下拉列表弹窗的高度,默认值100
* @param height
*/
void setPopupViewHeight(int height);
/**
* @brief selectedDataText 获取选择的数据
* @return
*/
QStringList selectedDataText();
/**
* @brief selectedUserData 获取选择数据对应的用户数据
* @return
*/
QList<QVariant> selectedUserData();
private slots:
void slot_itemChanged(QListWidgetItem *item);
private:
LLComboBoxPrivate *m_pd;
};
#endif // LLCOMBOBOX_H
#include
#include
#include
#include
#include
#include "llcombobox.h"
class LLComboBoxPrivate
{
public:
QStringList selectedDataList;
QListWidget *pListWidget;
};
LLComboBox::LLComboBox(QWidget *parent)
: QComboBox(parent)
, m_pd(new LLComboBoxPrivate)
{
m_pd->pListWidget = new QListWidget;
m_pd->pListWidget->setFixedHeight(100);
connect(m_pd->pListWidget, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(slot_itemChanged(QListWidgetItem *)));
setView(m_pd->pListWidget);
//设置Editable为true,lineEdit() 函数才不返回空
setEditable(true);
}
void LLComboBox::addDataItem(const QString &text, const QVariant &userData)
{
m_pd->pListWidget->blockSignals(true);
QListWidgetItem *pItem = new QListWidgetItem(text, m_pd->pListWidget);
pItem->setData(Qt::UserRole, userData);
pItem->setCheckState(Qt::Unchecked);
//设置QListWidgetItem 可交互且可以选中和取消选中
pItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
QComboBox::addItem(text);
QComboBox::setCurrentText("");
m_pd->pListWidget->blockSignals(false);
}
void LLComboBox::setSelectedData(const QStringList &selectedData)
{
m_pd->selectedDataList.clear();
m_pd->selectedDataList += selectedData;
QString text = "";
for (int var = 0; var < m_pd->selectedDataList.size(); ++var)
{
m_pd->pListWidget->blockSignals(true);
QListWidgetItem *pItem = m_pd->pListWidget->item(var);
pItem->setCheckState(Qt::Checked);
m_pd->pListWidget->blockSignals(false);
text.append(m_pd->selectedDataList[var]);
if(var < m_pd->selectedDataList.size() - 1)
{
text.append(",");
}
}
lineEdit()->setText(text);
}
QStringList LLComboBox::selectedDataText()
{
return m_pd->selectedDataList;
}
QList<QVariant> LLComboBox::selectedUserData()
{
QList<QVariant> dataList;
for (int var = 0; var < m_pd->selectedDataList.size(); ++var)
{
QListWidgetItem *pItem = m_pd->pListWidget->item(var);
if(pItem->checkState() == Qt::Checked)
{
dataList.append(pItem->data(Qt::UserRole));
}
}
return dataList;
}
void LLComboBox::slot_itemChanged(QListWidgetItem *item)
{
qDebug() << QString("text=") << item->text();
if(m_pd->selectedDataList.contains(item->text()))
{
m_pd->selectedDataList.removeOne(item->text());
}
else
{
m_pd->selectedDataList.append(item->text());
}
QString text = "";
for (int var = 0; var < m_pd->selectedDataList.size(); ++var)
{
text.append(m_pd->selectedDataList[var]);
if(var < m_pd->selectedDataList.size() - 1)
{
text.append(",");
}
}
lineEdit()->setText(text);
}
本控件继承自QComboBox,重新设置了QComboBox的弹出列表为 QListWidget 的实例pListWidget。当添加下拉列表元素时先创建一个QListWidgetItem,并通过setFlags 函数设置为可交互且用户可点击,通过setCheckState函数设置默认为非选中状态。需要注意的是必须调用 QComboBox::addItem(); 方法向QComboBox 添加数据,弹窗才能正常显示。
通过QListWidget 的 itemChanged(QListWidgetItem *)信号来判断一个选项是否选中,因此在添加数据前要先阻塞pListWidget的信号发送,添加结束后再开启信号发送。可以看到添加数据的代码是写在blockSignals();之间的。
m_pd->pListWidget->blockSignals(true);
//添加多选列表数据
m_pd->pListWidget->blockSignals(false);
QComboBox默认只显示一个选中的选项,为了显示选择的多个选项数据,这里设置QComboBox为可编辑,这样lineEdit()函数将返回编辑框指针,我们将多选的数据拼接起来设置到lineEdit中。如果不设置QComboBox为可编辑,lineEdit()函数将返回空指针。
在测试工程中,找一个UI,拖一个QComboBox组件到布局中,并将其提升为LLComboBox,如下图所示

在对应的cpp文件中,加入下面的测试代码
void TableWidgetTest::initComboBox()
{
QStringList dataList;
dataList << QString("语文") << QString("数学") << QString("英语") << QString("物理")
<< QString("化学") << QString("政治") << QString("体育") << QString("音乐");
for (int var = 0; var < dataList.size(); ++var)
{
ui->comboBox->addDataItem(dataList[var]);
}
QStringList seledataList;
seledataList << QString("语文") << QString("数学");
ui->comboBox->setSelectedData(seledataList);
}
编译运行程序,查看效果。
以上就是本文的所有内容了,欢迎留言讨论,源码下载地址 多选下拉列表下载地址