QComboBox的下拉多选

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、QComboBox的下拉多选
  • 二、实现原理
    • 1.下拉框点击不隐藏
    • 2.选中下拉项内容显示
  • 总结


前言

Qt的QComboBox实现下拉选择多个下拉项:
Qt默认的QComboBox在点击下拉时,每次只能有一个下拉项被选中;本文提供一种方式,实现通用的下拉多选效果。


一、QComboBox的下拉多选

默认的QComboBox点击下拉按钮,会有一个弹窗,默认只能选中一个选中项;在实际项目中,有可能会下拉勾选多个选项;本文通过在QComboBox的基础上实现对下拉条件的多选,效果如下:
QComboBox的下拉多选_第1张图片

二、实现原理

1.解决QComboBox下拉框在点击某个下拉项后,下拉框消失的问题;在经过一番研究发现,只需要重载QComboBox的 hidePopup()函数和showPopup()函数,能解决此问题。 2.自定义ComboBox中选中内容的显示 3.设置一个带勾选效果的QAbstractItemView给comBobox,便可实现下拉多选了;

1.下拉框点击不隐藏

主要重载QComboBox的两个函数
void CusMulSelectCombobox::hidePopup()
{
	//qDebug() << "hidePopup";
	
	//判断鼠标坐标是否在combobox区域内
	QRect rect = this->rect();
	QAbstractItemView* itemView = this->view();
	QAbstractItemModel* model = this->model();
	QPoint cursorPoint = itemView->mapFromGlobal(QCursor::pos());
	QRect viewRect = itemView->rect();

	//如果鼠标坐标在combobox的编辑区域内,关闭
	itemView->viewport()->update();
	if (!viewRect.contains(cursorPoint))
	{
		QComboBox::hidePopup();
		this->update();
		return;
	}
	// 目前导致一种情况,快捷键切换界面时,鼠标在combobox编辑内部,导致combobox不关闭,
	// 所以增加父窗口显隐判断,父窗口隐藏时,隐藏
	QWidget* tmpWidget = dynamic_cast<QWidget*>(parent());
	if (!tmpWidget->isVisible())
	{
		QComboBox::hidePopup();
		this->update();
		return;
	}
}
void CusMulSelectCombobox::showPopup()
{
	QStyle * const style = this->style();
	QStyleOptionComboBox opt;
	initStyleOption(&opt);
	QRect listRect(style->subControlRect(QStyle::CC_ComboBox, &opt,
		QStyle::SC_ComboBoxListBoxPopup, this));
	QPoint below = mapToGlobal(listRect.bottomLeft());//左下角坐标
    auto   s = qApp->screenAt(below);
    if (!s)
    {
        s = qApp->primaryScreen();
    }
    QRect    screen = s->geometry();
	QWidget *topWidget = QApplication::topLevelAt(QCursor::pos());
	if (!topWidget)
	{
		QComboBox::showPopup();
		return;
	}
	QRect topWidgetRect = topWidget->rect();
	QPoint topWidgetPoint = topWidget->mapToGlobal(QPoint(0, 0));
	int toScreenBottom = screen.height() - below.y();
	int toWidgetBottom = topWidgetPoint.y() + topWidgetRect.height() - below.y();
	int showCount = qMin(toScreenBottom, toWidgetBottom) / 30;
	if (showCount >= 10)
		this->setMaxVisibleItems(showCount);
	else
		this->setMaxVisibleItems(10);
	QComboBox::showPopup();
}

2.选中下拉项内容显示

重新实现currentText()函数,调用用户注册来的当下需要显示的内容回调;其中dPtr->mModelTextCb为回调函数,回调类型为:
typedef std::function<QString()> getModelTextCB;
QString CusMulSelectCombobox::currentText() const
{
	if (dPtr->mModelTextCb)
		return dPtr->mModelTextCb();
	return "";
}
通过重载void paintEvent(QPaintEvent *e)函数来实现当前选中内容的显示;
void CusMulSelectCombobox::paintEvent(QPaintEvent *e)
{
	QString curText = this->currentText();
	if (dPtr->mShowText != curText)
	{
		dPtr->mShowText = curText;
		this->setToolTip(dPtr->mShowText);
	}
	QStylePainter painter(this);
	painter.setPen(palette().color(QPalette::Text));

	// draw the combobox frame, focusrect and selected etc.
	QStyleOptionComboBox opt;
	QComboBox::initStyleOption(&opt);
	painter.drawComplexControl(QStyle::CC_ComboBox, opt);
	//修改要实现内容
	opt.currentText = curText;
	// draw the icon and text
	painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
}

总结

通过上述方式,在使用QComboBox,就可以根据需要实现列表,或者树型结构的下拉多选。

你可能感兴趣的:(Qt,qt,开发语言)