教你如何实现带复选框的ComboBox(自定义QComboBox)

您所在的位置:网站首页 qt中下拉框选择线条 教你如何实现带复选框的ComboBox(自定义QComboBox)

教你如何实现带复选框的ComboBox(自定义QComboBox)

#教你如何实现带复选框的ComboBox(自定义QComboBox)| 来源: 网络整理| 查看: 265

Qt提供的QComboBox只能选择其中一个选项,无法实现同时选中多个,而实际工程项目中,下拉框中带复选框的需求比比皆是。阅读了网上大量的博客,但是没有发现一个能完美的实现该功能的ComboBox,都存在各种未解决的bug缺陷,样子是那么回事儿,但是里子经不起推敲。经过笔者多次熬夜,接近通宵,工程中反复使用、测试,bug逐渐被解决。

请读者转载时,注明来源,谢谢!!!

废话不多说,下面就教大家如何实现。

一、效果图

1、初始化样式

2、展开样式

3、选择多个item的样式

4、选择后的样式,鼠标hover时,显示被选中的item文本

二、源码展示

1、头文件XComboBox.h

#pragma once #include #include #include #include class QLineEdit; struct ItemInfo { int idx; QString str; QVariant userData; bool bChecked; ItemInfo() { idx = -1; str = QString(""); 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(event); if (keyEvent->key() == Qt::Key_Space) { QListView* lstV = qobject_cast(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& lstItemInfo); void AddItems(const QMap& mapStrChk); void AddItems(const QList& lstStr); // 删除item void RemoveItem(int idx); // 清空item void Clear(); // 获取选中的数据字符串列表 QStringList GetSelItemsText(); // 获取选中item的信息 QList 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 #include 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); connect(this, SIGNAL(activated(int)), this, SLOT(sltActivated(int))); connect(keyPressEater, SIGNAL(sigActivated(int)), this, SLOT(sltActivated(int))); } 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& lstItemInfo) { for (auto a : lstItemInfo) { AddItem(a.str, a.bChecked, a.userData); } } void XComboBox::AddItems(const QMap& mapStrChk) { for (auto it = mapStrChk.begin(); it != mapStrChk.end(); ++it) { AddItem(it.key(), it.value()); } } void XComboBox::AddItems(const QList& lstStr) { for (auto a : lstStr) { AddItem(a, false); } } void XComboBox::RemoveItem(int idx) { m_model.removeRow(idx); UpdateText(); } void XComboBox::Clear() { m_model.clear(); UpdateText(); } QStringList XComboBox::GetSelItemsText() { QStringList lst; QString str = pLineEdit->text(); if (str.isEmpty()) { return lst; } else { lst = pLineEdit->text().split(","); return lst; } } QList XComboBox::GetSelItemsInfo() { QList lstInfo; for (int i = 0; i < m_model.rowCount(); i++) { QStandardItem* item = m_model.item(i); if (item->checkState() == Qt::Unchecked) continue; ItemInfo info; info.idx = i; info.str = item->text(); info.bChecked = true; info.userData = item->data(Qt::UserRole + 1); lstInfo = m_model.rowCount()) { return QString(""); } return m_model.item(idx)->text(); } ItemInfo XComboBox::GetItemInfo(int idx) { ItemInfo info; if (idx < 0 || idx >= m_model.rowCount()) { return info; } QStandardItem* item = m_model.item(idx); info.idx = idx; info.str = item->text(); info.bChecked = (item->checkState() == Qt::Checked); info.userData = item->data(Qt::UserRole + 1); return info; } // 查找目标项,找到则返回所在行号,否则返回-1 int XComboBox::FindItem(const QVariant &Key) const { for (int nRow = 0; nRow < m_model.rowCount(); nRow++) { QStandardItem *pItem = m_model.item(nRow); if (pItem == nullptr) { continue; } if (pItem->data(Qt::UserRole + 1) == Key) { return nRow; } } return -1; } void XComboBox::showPopup() { emit showingPopup(); QComboBox::showPopup(); } void XComboBox::hidePopup() { int width = this->view()->width(); int height = this->view()->height(); int x = QCursor::pos().x() - mapToGlobal(geometry().topLeft()).x() + geometry().x(); int y = QCursor::pos().y() - mapToGlobal(geometry().topLeft()).y() + geometry().y(); QRect rectView(0, this->height(), width, height); if (!rectView.contains(x, y)) { emit hidingPopup(); QComboBox::hidePopup(); } } void XComboBox::mousePressEvent(QMouseEvent * event) { QComboBox::mousePressEvent(event); event->accept(); } void XComboBox::mouseReleaseEvent(QMouseEvent * event) { QComboBox::mouseReleaseEvent(event); event->accept(); } void XComboBox::mouseMoveEvent(QMouseEvent * event) { QComboBox::mouseMoveEvent(event); event->accept(); } void XComboBox::UpdateText() { QStringList lstTxt; for (int i = 0; i < m_model.rowCount(); ++i) { QStandardItem* item = m_model.item(i); if (item->checkState() == Qt::Unchecked) continue; lstTxt text(); } pLineEdit->setText(lstTxt.join(",")); pLineEdit->setToolTip(lstTxt.join("\n")); } void XComboBox::sltActivated(int idx) { QStandardItem* item = m_model.item(idx); if (nullptr == item) return; Qt::CheckState state = (item->checkState() == Qt::Checked) ? Qt::Unchecked : Qt::Checked; item->setCheckState(state); UpdateText(); sigItemStateChanged(); }

3、测试代码

QStringList lstStr; for (int i=0; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3