提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
Qt的QComboBox实现下拉选择多个下拉项:
Qt默认的QComboBox在点击下拉时,每次只能有一个下拉项被选中;本文提供一种方式,实现通用的下拉多选效果。
一、QComboBox的下拉多选
默认的QComboBox点击下拉按钮,会有一个弹窗,默认只能选中一个选中项;在实际项目中,有可能会下拉勾选多个选项;本文通过在QComboBox的基础上实现对下拉条件的多选,效果如下:
二、实现原理
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);
}