头文件

  1. #ifndef _CHECK_COMBOX_H
  2. #define _CHECK_COMBOX_H
  3. #include <QComboBox>
  4. #include <QKeyEvent>
  5. #include <QListView>
  6. #include <QStandardItemModel>
  7. class QLineEdit;
  8. class QListView;
  9. struct ItemInfo {
  10. int idx;
  11. QString str;
  12. QVariant userData;
  13. bool bChecked;
  14. ItemInfo()
  15. {
  16. idx = -1;
  17. str = QString("");
  18. userData = QVariant();
  19. bChecked = false;
  20. }
  21. };
  22. // 事件过滤器
  23. class KeyPressEater : public QObject {
  24. Q_OBJECT
  25. public:
  26. KeyPressEater(QObject* parent = nullptr)
  27. : QObject(parent)
  28. {
  29. }
  30. ~KeyPressEater() { }
  31. signals:
  32. void sigActivated(int idx);
  33. protected:
  34. bool eventFilter(QObject* obj, QEvent* event)
  35. {
  36. if (event->type() == QEvent::KeyPress) {
  37. QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
  38. if (keyEvent->key() == Qt::Key_Space) {
  39. QListView* lstV = qobject_cast<QListView*>(obj);
  40. if (nullptr != lstV) {
  41. int idx = lstV->currentIndex().row();
  42. if (-1 != idx) {
  43. emit sigActivated(idx);
  44. }
  45. }
  46. } else if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down) {
  47. return QObject::eventFilter(obj, event);
  48. }
  49. return true;
  50. } else {
  51. // standard event processing
  52. return QObject::eventFilter(obj, event);
  53. }
  54. }
  55. };
  56. class MyComboBox : public QComboBox {
  57. Q_OBJECT
  58. public:
  59. MyComboBox(QWidget* parent = Q_NULLPTR);
  60. ~MyComboBox();
  61. // 添加item
  62. void AddItem(const QString& str, bool bChecked = false, QVariant userData = QVariant());
  63. void AddItems(const QList<ItemInfo>& lstItemInfo);
  64. void AddItems(const QMap<QString, bool>& mapStrChk);
  65. void AddItems(const QList<QString>& lstStr);
  66. // 删除item
  67. void RemoveItem(int idx);
  68. // 清空item
  69. void Clear();
  70. // 获取选中的数据字符串列表
  71. QStringList GetSelItemsText();
  72. // 获取选中item的信息
  73. QList<ItemInfo> GetSelItemsInfo();
  74. // 获取item文本
  75. QString GetItemText(int idx);
  76. // 获取item信息
  77. ItemInfo GetItemInfo(int idx);
  78. signals:
  79. // popup显示信号
  80. void showingPopup();
  81. // popup隐藏信号
  82. void hidingPopup();
  83. protected:
  84. void showPopup();
  85. // 重写QComboBox的hidePopup函数
  86. // 目的选择过程中,不隐藏listview
  87. void hidePopup();
  88. virtual void mousePressEvent(QMouseEvent* event);
  89. virtual void mouseReleaseEvent(QMouseEvent* event);
  90. virtual void mouseMoveEvent(QMouseEvent* event);
  91. private:
  92. void UpdateText();
  93. private slots:
  94. void sltActivated(int idx);
  95. private:
  96. QLineEdit* pLineEdit;
  97. QListView* pListView;
  98. QStandardItemModel m_model;
  99. };
  100. #endif

实现

  1. #include "ccheckcombobox.h"
  2. #include <QDebug>
  3. #include <QLineEdit>
  4. #include <QMouseEvent>
  5. MyComboBox::MyComboBox(QWidget* parent)
  6. : QComboBox(parent)
  7. {
  8. pLineEdit = new QLineEdit(this);
  9. pLineEdit->setReadOnly(true);
  10. this->setLineEdit(pLineEdit);
  11. this->lineEdit()->disconnect();
  12. KeyPressEater* keyPressEater = new KeyPressEater(this);
  13. pListView = new QListView(this);
  14. pListView->installEventFilter(keyPressEater);
  15. this->setView(pListView);
  16. this->setModel(&m_model);
  17. connect(this, SIGNAL(activated(int)), this, SLOT(sltActivated(int)));
  18. connect(keyPressEater, SIGNAL(sigActivated(int)), this, SLOT(sltActivated(int)));
  19. }
  20. MyComboBox::~MyComboBox()
  21. {
  22. }
  23. void MyComboBox::AddItem(const QString& str, bool bChecked /*= false*/, QVariant userData /*= QVariant()*/)
  24. {
  25. QStandardItem* item = new QStandardItem(str);
  26. item->setCheckable(true);
  27. item->setCheckState(bChecked ? Qt::Checked : Qt::Unchecked);
  28. item->setData(userData, Qt::UserRole + 1);
  29. m_model.appendRow(item);
  30. UpdateText();
  31. }
  32. void MyComboBox::AddItems(const QList<ItemInfo>& lstItemInfo)
  33. {
  34. for (auto a : lstItemInfo) {
  35. AddItem(a.str, a.bChecked, a.userData);
  36. }
  37. }
  38. void MyComboBox::AddItems(const QMap<QString, bool>& mapStrChk)
  39. {
  40. for (auto it = mapStrChk.begin(); it != mapStrChk.end(); ++it) {
  41. AddItem(it.key(), it.value());
  42. }
  43. }
  44. void MyComboBox::AddItems(const QList<QString>& lstStr)
  45. {
  46. for (auto a : lstStr) {
  47. AddItem(a, false);
  48. }
  49. }
  50. void MyComboBox::RemoveItem(int idx)
  51. {
  52. m_model.removeRow(idx);
  53. UpdateText();
  54. }
  55. void MyComboBox::Clear()
  56. {
  57. m_model.clear();
  58. UpdateText();
  59. }
  60. QStringList MyComboBox::GetSelItemsText()
  61. {
  62. QStringList lst;
  63. QString str = pLineEdit->text();
  64. if (str.isEmpty()) {
  65. return lst;
  66. } else {
  67. return pLineEdit->text().split(",");
  68. }
  69. }
  70. QList<ItemInfo> MyComboBox::GetSelItemsInfo()
  71. {
  72. QList<ItemInfo> lstInfo;
  73. for (int i = 0; i < m_model.rowCount(); i++) {
  74. QStandardItem* item = m_model.item(i);
  75. if (item->checkState() == Qt::Unchecked)
  76. continue;
  77. ItemInfo info;
  78. info.idx = i;
  79. info.str = item->text();
  80. info.bChecked = true;
  81. info.userData = item->data(Qt::UserRole + 1);
  82. lstInfo << info;
  83. }
  84. return lstInfo;
  85. }
  86. QString MyComboBox::GetItemText(int idx)
  87. {
  88. if (idx < 0 || idx >= m_model.rowCount()) {
  89. return QString("");
  90. }
  91. return m_model.item(idx)->text();
  92. }
  93. ItemInfo MyComboBox::GetItemInfo(int idx)
  94. {
  95. ItemInfo info;
  96. if (idx < 0 || idx >= m_model.rowCount()) {
  97. return info;
  98. }
  99. QStandardItem* item = m_model.item(idx);
  100. info.idx = idx;
  101. info.str = item->text();
  102. info.bChecked = (item->checkState() == Qt::Checked);
  103. info.userData = item->data(Qt::UserRole + 1);
  104. return info;
  105. }
  106. void MyComboBox::showPopup()
  107. {
  108. emit showingPopup();
  109. QComboBox::showPopup();
  110. }
  111. void MyComboBox::hidePopup()
  112. {
  113. int width = this->view()->width();
  114. int height = this->view()->height();
  115. int x = QCursor::pos().x() - mapToGlobal(geometry().topLeft()).x() + geometry().x();
  116. int y = QCursor::pos().y() - mapToGlobal(geometry().topLeft()).y() + geometry().y();
  117. QRect rectView(0, this->height(), width, height);
  118. if (!rectView.contains(x, y)) {
  119. emit hidingPopup();
  120. QComboBox::hidePopup();
  121. }
  122. }
  123. void MyComboBox::mousePressEvent(QMouseEvent* event)
  124. {
  125. QComboBox::mousePressEvent(event);
  126. event->accept();
  127. }
  128. void MyComboBox::mouseReleaseEvent(QMouseEvent* event)
  129. {
  130. QComboBox::mouseReleaseEvent(event);
  131. event->accept();
  132. }
  133. void MyComboBox::mouseMoveEvent(QMouseEvent* event)
  134. {
  135. QComboBox::mouseMoveEvent(event);
  136. event->accept();
  137. }
  138. void MyComboBox::UpdateText()
  139. {
  140. QStringList lstTxt;
  141. for (int i = 0; i < m_model.rowCount(); ++i) {
  142. QStandardItem* item = m_model.item(i);
  143. if (item->checkState() == Qt::Unchecked)
  144. continue;
  145. lstTxt << item->text();
  146. }
  147. pLineEdit->setText(lstTxt.join(","));
  148. pLineEdit->setToolTip(lstTxt.join("\n"));
  149. }
  150. void MyComboBox::sltActivated(int idx)
  151. {
  152. QStandardItem* item = m_model.item(idx);
  153. if (nullptr == item)
  154. return;
  155. Qt::CheckState state = (item->checkState() == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
  156. item->setCheckState(state);
  157. UpdateText();
  158. }

使用

  1. MyComboBox combox;
  2. QStringList lstStr;
  3. for (int i = 0; i < 10; ++i) {
  4. lstStr << QString("item %1").arg(i);
  5. }
  6. combox.AddItems(lstStr);