因项目需求,需要实现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);