重写QComboBox,实现下拉复选框

基本效果如下图:重写QComboBox实现能够多选的效果

在这里插入图片描述

代码实现

头文件

#include<QComboBox>
class MultiSelectComboBox :public QComboBox
{
	Q_OBJECT
public:
	explicit MultiSelectComboBox(QWidget *parent = 0);
public:
	bool eventFilter(QObject*watched, QEvent*event) override;
	void hidePopup() override;
	void showPopup() override;
	QStringList checkedItems() const;
	void setCheckedItems(const QStringList& items);
public slots:
	void onItemStateChanged();
	void onInstallFilters();
	void updateLineEditText(const QString &text);
};



源文件

#include <QMouseEvent>
#include <QKeyEvent>
#include <QAbstractItemView>
#include <QTimer>
#include <QLineEdit>
#include "MultiSelectComboBox.h"

MultiSelectComboBox::MultiSelectComboBox(QWidget *parent) : QComboBox(parent)
{
	this->setEditable(true);
	QTimer::singleShot(0, this, &MultiSelectComboBox::onInstallFilters); //延迟安装事件过滤器,确保界面初始化完成

	connect(model(), &QAbstractItemModel::dataChanged, this, &MultiSelectComboBox::onItemStateChanged);
}

MultiSelectComboBox::~MultiSelectComboBox()
{

}

void MultiSelectComboBox::onInstallFilters()
{
	if (this->view() && this->view()->viewport())
	{
		this->view()->viewport()->installEventFilter(this);
	}
	if (this->lineEdit())
	{
		this->lineEdit()->setReadOnly(true);
	}
}

void MultiSelectComboBox::updateLineEditText(const QString &text)
{
	Q_UNUSED(text);
	this->lineEdit()->setText(checkedItems().join(";"));
}

bool MultiSelectComboBox::eventFilter(QObject* obj, QEvent* event)
{
	if (obj == this->view()->viewport() && event->type() == QEvent::MouseButtonRelease)
	{
		QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
		QModelIndex index = view()->indexAt(mouseEvent->pos());

		if (index.isValid())
		{
			bool checked = model()->data(index, Qt::CheckStateRole).toBool();
			if (checked && checkedItems().count() == 1)  // 确保至少选择一项
			{
				return true;
			}
			model()->setData(index, !checked, Qt::CheckStateRole);
			return true;
		}
	}
	return QComboBox::eventFilter(obj, event);
}

void MultiSelectComboBox::hidePopup()
{
	setCurrentText(checkedItems().join(";"));
	QComboBox::hidePopup();
}

void MultiSelectComboBox::showPopup()
{
	QStringList selectedItems = currentText().split(";");
	for (int i = 0; i < count(); ++i)
	{
		setItemData(i, selectedItems.contains(itemText(i)), Qt::CheckStateRole);
	}
	QComboBox::showPopup();
}

QStringList MultiSelectComboBox::checkedItems() const
{
	QStringList items;
	for (int i = 0; i < count(); ++i)
	{
		if (itemData(i, Qt::CheckStateRole).toBool())
		{
			items << itemText(i);
		}
	}
	return items;
}

void MultiSelectComboBox::setCheckedItems(const QStringList& items)
{
	for (int i = 0; i < count(); ++i)
	{
		setItemData(i, items.contains(itemText(i)), Qt::CheckStateRole);
	}
	setCurrentText(items.join(";"));
}

void MultiSelectComboBox::onItemStateChanged()
{
	QStringList selectedItems = checkedItems();
	QString newText = selectedItems.join(";");
	if (currentText() != newText)
	{
		setCurrentText(newText);
	}
}


使用方法

方式一:继承 MultiSelectComboBox类,new一个对象
方式二:使用qt designer把QComboBox提升

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值