教你如何实现带复选框的ComboBox(⾃定义QComboBox)Qt提供的QComboBox只能选择其中⼀个选项,⽆法实现同时选中多个,⽽实际⼯程项⽬中,下拉框中带复选框的需求⽐⽐皆是。阅读了⽹上⼤量的博客,但是没有发现⼀个能完美的实现该功能的ComboBox,都存在各种未解决的bug缺陷,样⼦是那么回事⼉,但是⾥⼦经不起推敲。经过笔者多次熬夜,接近通宵,⼯程中反复使⽤、测试,bug逐渐被解决。
请读者转载时,注明来源,谢谢
废话不多说,下⾯就教⼤家如何实现。
⼀、效果图
1、初始化样式
2、展开样式
3、选择多个item的样式
4、选择后的样式,⿏标hover时,显⽰被选中的item⽂本
⼆、源码展⽰
1、头⽂件XComboBox.h
#pragma once
#include <QComboBox>
#include <QStandardItemModel>
#include <QKeyEvent>
#include <QListView>
class QLineEdit;
struct ItemInfo
{
int idx;
QString str;
QVariant userData;
bool bChecked;
ItemInfo()
{
userData = QVariant();
bChecked = false;
}
};
class KeyPressEater : public QObject
{
Q_OBJECT
public:
KeyPressEater(QObject* parent = nullptr) :QObject(parent) {}
~KeyPressEater() {}
signals:
void sigActivated(int idx);
protected:
bool eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Space)
{
QListView* lstV = qobject_cast<QListView*>(obj);
if (nullptr != lstV)
{
int idx = lstV->currentIndex().row();
if (-1 != idx)
{
emit sigActivated(idx);
}
}
}
else if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down)
{
return QObject::eventFilter(obj, event);
}
return true;
}
else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}
};
class XComboBox : public QComboBox
{
Q_OBJECT
public:
XComboBox(QWidget *parent = Q_NULLPTR);
~XComboBox();
// 添加item
void AddItem(const QString& str, bool bChecked = false, QVariant &userData = QVariant());    void AddItems(const QList<ItemInfo>& lstItemInfo);
void AddItems(const QMap<QString, bool>& mapStrChk);
void AddItems(const QList<QString>& lstStr);
// 删除item
void RemoveItem(int idx);
// 清空item
QStringList GetSelItemsText();
// 获取选中item的信息
QList<ItemInfo> GetSelItemsInfo();
// 获取item⽂本
QString GetItemText(int idx);
// 获取item信息
ItemInfo GetItemInfo(int idx);
// 查⽬标项,到则返回所在⾏号,否则返回-1
int FindItem(const QVariant &Key) const;
signals:
// popup显⽰信号
void showingPopup();
// popup隐藏信号
void hidingPopup();
// item选中状态发⽣变化
void sigItemStateChanged();
protected:
void showPopup();
// 重写QComboBox的hidePopup函数
// ⽬的选择过程中,不隐藏listview
void hidePopup();
virtual void mousePressEvent(QMouseEvent * event);
virtual void mouseReleaseEvent(QMouseEvent * event);    virtual void mouseMoveEvent(QMouseEvent * event);
private:
void UpdateText();
private slots:
void sltActivated(int idx);
private:
QLineEdit* pLineEdit;
QListView* pListView;
QStandardItemModel m_model;
};
2、源⽂件XComboBox.cpp
#include "XComboBox.h"
#include <QLineEdit>
#include <QMouseEvent>
XComboBox::XComboBox(QWidget *parent)
: QComboBox(parent)
{
pLineEdit = new QLineEdit(this);
pLineEdit->setReadOnly(true);
this->setLineEdit(pLineEdit);
this->lineEdit()->disconnect();
KeyPressEater *keyPressEater = new KeyPressEater(this);    pListView = new QListView(this);
pListView->installEventFilter(keyPressEater);
this->setView(pListView);
this->setModel(&m_model);
}
XComboBox::~XComboBox()
{
}
void XComboBox::AddItem(const QString& str, bool bChecked /*= false*/, QVariant &userData /*= QVariant()*/) {
QStandardItem* item = new QStandardItem(str);
item->setCheckable(true);
item->setCheckState(bChecked ? Qt::Checked : Qt::Unchecked);
item->setData(userData, Qt::UserRole + 1);
m_model.appendRow(item);
UpdateText();
}
void XComboBox::AddItems(const QList<ItemInfo>& lstItemInfo)
{
for (auto a : lstItemInfo)
{
AddItem(a.str, a.bChecked, a.userData);
}
}
void XComboBox::AddItems(const QMap<QString, bool>& mapStrChk)
{
for (auto it = mapStrChk.begin(); it != d(); ++it)
{
AddItem(it.key(), it.value());
}
}
void XComboBox::AddItems(const QList<QString>& lstStr)
{
for (auto a : lstStr)
{
AddItem(a, false);
}
}
void XComboBox::RemoveItem(int idx)
{
veRow(idx);
UpdateText();
}
void XComboBox::Clear()
{
m_model.clear();
UpdateText();
}
QStringList XComboBox::GetSelItemsText()
{
QStringList lst;
QString str = pLineEdit->text();
if (str.isEmpty())
{
return lst;
qt listview
}
else
{

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。