首页 >> 大全

Qt 下拉复选框(MultiSelectComboBox)(一) 实现下拉框多选

2023-08-25 大全 31 作者:考证青年

文章目录 4. 对外接口定义5. 代码实现 总结

本系列目录

Qt 下拉复选框()(一) 实现下拉框多选,搜索下拉框内容

Qt 下拉复选框()(二) 样式表设置

Qt 下拉复选框()(三) 不能输入中文等问题修复

前言

刚开始学习qt时,在遇到下拉复选框问题的时候总是使用表格来实现这个功能,因为表格单元格可以添加代理,而类对象在设置代理后总是不生效。使用表格来实现,如果需求本来就是在表格中还好,但有时候只是需要一个下拉复选框,这个时候就需要隐藏边框,设置单元双击输入框禁用等等,会非常麻烦,而且最后的效果也是不敬人意,所以在仔细研究了类对象之后,参考大佬的示例实现了一个比较好用的下拉复选框。

参考博客地址:

以下是本篇文章正文内容,主要实现功能,下面案例可供参考

一、的组成

类对象由三部分组成:、、。

二、实现 1. 总体实现

整个控件继承于类。主要修改、这两部分,提供如下接口,可以将这两部分设置为新建的、对象 ( ,)。

代码如下(示例):

this->setView(list_widget_);
this->setLineEdit(line_edit_);

2. 部分

这部分用来显示选择的结果和弹出下拉框,显示内容使用 “;” 进行分割。这里设置了点击也可以弹出下拉框,需要先将当前对象安装(或注册)为事件过滤器,再重写()函数。

代码如下(示例):

    /*设置文本框*///设为只读,因为该输入框只用来显示选中选项,称为文本框更合适些line_edit_->setReadOnly(true);//把当前对象安装(或注册)为事件过滤器,当前也称为过滤器对象。事件过滤器通常在构造函数中进行注册。line_edit_->installEventFilter(this);//设置禁用样式,因为不受样式表控制,临时这样解决line_edit_->setStyleSheet("QLineEdit:disabled{background:rgb(233,233,233);}");bool MultiSelectComboBox::eventFilter(QObject *watched, QEvent *event)
{//设置点击输入框也可以弹出下拉框if (watched == line_edit_ && event->type() == QEvent::MouseButtonRelease && this->isEnabled()){showPopup();return true;}return false;
}

3. 部分

下拉框部分,显示搜索框与选项。

1. 搜索框部分

设置第一项的为,用来输入检索条件,绑定(const &)信号,当输入内容发生变化时,下面显示选项发生相应变化。

初始化代码如下(示例):

/*设置搜索框*/QListWidgetItem* currentItem = new QListWidgetItem(list_widget_);//设置搜索框提示信息search_bar_->setPlaceholderText("Search.........");//显示清除按钮search_bar_->setClearButtonEnabled(true);list_widget_->addItem(currentItem);list_widget_->setItemWidget(currentItem, search_bar_);

输入文本变化槽函数代码如下(示例):

connect(search_bar_, SIGNAL(textChanged(const QString&)), this, SLOT(onSearch(const QString&)));

void MultiSelectComboBox::onSearch(const QString& _text)
{for (int i = 1; i < list_widget_->count(); i++){QCheckBox *check_box = static_cast<QCheckBox*>(list_widget_->itemWidget(list_widget_->item(i)));//文本匹配则显示,反之隐藏//Qt::CaseInsensitive模糊查询if (check_box->text().contains(_text, Qt::CaseInsensitive))list_widget_->item(i)->setHidden(false);elselist_widget_->item(i)->setHidden(true);}
}

2. 选项部分

单击选项选中,选中后更新内容,绑定信号,鼠标单击选项时时,就会将所有选项遍历一遍,然后把选中的选项组织为字符串,更新到上。发送信号void (const _data);,此信号为选中选项发送变化时发出。

选项变化槽函数代码如下(示例):

connect(checkbox, &QCheckBox::stateChanged, this, &MultiSelectComboBox::stateChange);

void MultiSelectComboBox::stateChange(int _row)
{Q_UNUSED(_row);QString selected_data("");int count = list_widget_->count();for (int i = 1; i < count; i++){QWidget *widget = list_widget_->itemWidget(list_widget_->item(i));QCheckBox *check_box = static_cast<QCheckBox*>(widget);if (check_box->isChecked()){selected_data.append(check_box->text()).append(";");}}selected_data.chop(1);if (!selected_data.isEmpty()){line_edit_->setText(selected_data);}else{line_edit_->clear();}line_edit_->setToolTip(selected_data);emit selectionChange(selected_data);
}

4. 对外接口定义

考虑到使用方便,这里定义了一些接口方便用户使用,接口含义见下方注释 (文本框代表)。

接口定义如下(示例):

    //隐藏下拉框virtual void hidePopup();//添加一条选项void addItem(const QString& _text, const QVariant& _variant = QVariant());//添加多条选项void addItems(const QStringList& _text_list);//返回当前选中选项QStringList currentText();//返回当前选项条数int count()const;//设置搜索框默认文字void SetSearchBarPlaceHolderText(const QString _text);//设置文本框默认文字void SetPlaceHolderText(const QString& _text);//下拉框状态恢复默认(所有选项都恢复为未选中状态)void ResetSelection();//清空所有内容(选项内容全部清空)void clear();//文本框内容清空(选项内容不清空,所有选项都恢复为未选中状态,文本框清空)void TextClear();//设置选中文本--单void setCurrentText(const QString& _text);//设置选中文本--多void setCurrentText(const QStringList& _text_list);//设置搜索框是否禁用void SetSearchBarHidden(bool _flag);

5. 代码实现

头文件:

#pragma once#include <QComboBox>
#include <QListWidget>
#include <QLineEdit>
#include <QCheckBox>
#include <QEvent>class MultiSelectComboBox : public QComboBox
{Q_OBJECTpublic:MultiSelectComboBox(QWidget *parent = Q_NULLPTR);~MultiSelectComboBox();//隐藏下拉框virtual void hidePopup();//添加一条选项void addItem(const QString& _text, const QVariant& _variant = QVariant());//添加多条选项void addItems(const QStringList& _text_list);//返回当前选中选项QStringList currentText();//返回当前选项条数int count()const;//设置搜索框默认文字void SetSearchBarPlaceHolderText(const QString _text);//设置文本框默认文字void SetPlaceHolderText(const QString& _text);//下拉框状态恢复默认void ResetSelection();//清空所有内容void clear();//文本框内容清空void TextClear();//设置选中文本--单void setCurrentText(const QString& _text);//设置选中文本--多void setCurrentText(const QStringList& _text_list);//设置搜索框是否禁用void SetSearchBarHidden(bool _flag);protected://事件过滤器virtual bool eventFilter(QObject *watched,QEvent *event);//滚轮事件virtual void wheelEvent(QWheelEvent *event);//按键事件virtual void keyPressEvent(QKeyEvent *event);private slots://槽函数:文本框文本变化void stateChange(int _row);//槽函数:搜索框文本变化void onSearch(const QString& _text);//槽函数:点击下拉框选项void itemClicked(int _index);signals://信号:发送当前选中选项void selectionChange(const QString _data);private://下拉框QListWidget* list_widget_;//文本框,搜索框QLineEdit* line_edit_, *search_bar_;//搜索框显示标志bool hidden_flag_;//下拉框显示标志bool show_flag_;
};

实现:

#include "multi_select_combobox.h"MultiSelectComboBox::MultiSelectComboBox(QWidget *parent): QComboBox(parent), hidden_flag_(true), show_flag_(false)
{list_widget_ = new QListWidget();line_edit_ = new QLineEdit();search_bar_ = new QLineEdit();/*设置搜索框*/QListWidgetItem* currentItem = new QListWidgetItem(list_widget_);//设置搜索框提示信息search_bar_->setPlaceholderText("Search.........");//显示清除按钮search_bar_->setClearButtonEnabled(true);list_widget_->addItem(currentItem);list_widget_->setItemWidget(currentItem, search_bar_);/*设置文本框*///设为只读,因为该输入框只用来显示选中的选项,称为文本框更合适些line_edit_->setReadOnly(true);//把当前对象安装(或注册)为事件过滤器,当前也称为过滤器对象。事件过滤器通常在构造函数中进行注册。line_edit_->installEventFilter(this);//设置禁用样式,因为不受样式表控制,临时这样解决line_edit_->setStyleSheet("QLineEdit:disabled{background:rgb(233,233,233);}");this->setModel(list_widget_->model());this->setView(list_widget_);this->setLineEdit(line_edit_);connect(search_bar_, SIGNAL(textChanged(const QString&)), this, SLOT(onSearch(const QString&)));connect(this, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &MultiSelectComboBox::itemClicked);
}MultiSelectComboBox::~MultiSelectComboBox()
{
}void MultiSelectComboBox::hidePopup()
{show_flag_ = false;int width = this->width();int height = this->height();int x = QCursor::pos().x() - mapToGlobal(geometry().topLeft()).x() + geometry().x();int y = QCursor::pos().y() - mapToGlobal(geometry().topLeft()).y() + geometry().y();if (x >= 0 && x <= width && y >= this->height() && y <= height + this->height()){}else{QComboBox::hidePopup();}
}void MultiSelectComboBox::addItem(const QString& _text, const QVariant& _variant /*= QVariant()*/)
{Q_UNUSED(_variant);QListWidgetItem* item = new QListWidgetItem(list_widget_);QCheckBox* checkbox = new QCheckBox(this);checkbox->setText(_text);list_widget_->addItem(item);list_widget_->setItemWidget(item, checkbox);connect(checkbox, &QCheckBox::stateChanged, this, &MultiSelectComboBox::stateChange);
}void MultiSelectComboBox::addItems(const QStringList& _text_list)
{for (const auto& text_one : _text_list){addItem(text_one);}
}QStringList MultiSelectComboBox::currentText()
{QStringList text_list;if (!line_edit_->text().isEmpty()){//以;为分隔符分割字符串text_list = line_edit_->text().split(':');}return text_list;
}int MultiSelectComboBox::count() const
{int count = list_widget_->count() - 1;if (count < 0){count = 0;}return count;
}void MultiSelectComboBox::SetSearchBarPlaceHolderText(const QString _text)
{search_bar_->setPlaceholderText(_text);
}void MultiSelectComboBox::SetPlaceHolderText(const QString& _text)
{line_edit_->setPlaceholderText(_text);
}void MultiSelectComboBox::ResetSelection()
{int count = list_widget_->count();for (int i = 1; i < count; i++){//获取对应位置的QWidget对象QWidget *widget = list_widget_->itemWidget(list_widget_->item(i));//将QWidget对象转换成对应的类型QCheckBox *check_box = static_cast<QCheckBox*>(widget);check_box->setChecked(false);}
}void MultiSelectComboBox::clear()
{line_edit_->clear();list_widget_->clear();QListWidgetItem* currentItem = new QListWidgetItem(list_widget_);search_bar_->setPlaceholderText("Search.........");search_bar_->setClearButtonEnabled(true);list_widget_->addItem(currentItem);list_widget_->setItemWidget(currentItem, search_bar_);SetSearchBarHidden(hidden_flag_);connect(search_bar_, SIGNAL(textChanged(const QString&)), this, SLOT(onSearch(const QString&)));
}void MultiSelectComboBox::TextClear()
{line_edit_->clear();ResetSelection();
}void MultiSelectComboBox::setCurrentText(const QString& _text)
{int count = list_widget_->count();for (int i = 1; i < count; i++){//获取对应位置的QWidget对象QWidget *widget = list_widget_->itemWidget(list_widget_->item(i));//将QWidget对象转换成对应的类型QCheckBox *check_box = static_cast<QCheckBox*>(widget);if (_text.compare(check_box->text()))check_box->setChecked(true);}
}void MultiSelectComboBox::setCurrentText(const QStringList& _text_list)
{int count = list_widget_->count();for (int i = 1; i < count; i++){//获取对应位置的QWidget对象QWidget *widget = list_widget_->itemWidget(list_widget_->item(i));//将QWidget对象转换成对应的类型QCheckBox *check_box = static_cast<QCheckBox*>(widget);if (_text_list.contains(check_box->text()))check_box->setChecked(true);	}
}void MultiSelectComboBox::SetSearchBarHidden(bool _flag)
{hidden_flag_ = _flag;list_widget_->item(0)->setHidden(hidden_flag_);
}bool MultiSelectComboBox::eventFilter(QObject *watched, QEvent *event)
{//设置点击输入框也可以弹出下拉框if (watched == line_edit_ && event->type() == QEvent::MouseButtonRelease && this->isEnabled()){showPopup();return true;}return false;
}void MultiSelectComboBox::wheelEvent(QWheelEvent *event)
{//禁用QComboBox默认的滚轮事件Q_UNUSED(event);
}void MultiSelectComboBox::keyPressEvent(QKeyEvent *event)
{QComboBox::keyPressEvent(event);
}void MultiSelectComboBox::stateChange(int _row)
{Q_UNUSED(_row);QString selected_data("");int count = list_widget_->count();for (int i = 1; i < count; i++){QWidget *widget = list_widget_->itemWidget(list_widget_->item(i));QCheckBox *check_box = static_cast<QCheckBox*>(widget);if (check_box->isChecked()){selected_data.append(check_box->text()).append(";");}}selected_data.chop(1);if (!selected_data.isEmpty()){line_edit_->setText(selected_data);}else{line_edit_->clear();}line_edit_->setToolTip(selected_data);emit selectionChange(selected_data);
}void MultiSelectComboBox::onSearch(const QString& _text)
{for (int i = 1; i < list_widget_->count(); i++){QCheckBox *check_box = static_cast<QCheckBox*>(list_widget_->itemWidget(list_widget_->item(i)));//文本匹配则显示,反之隐藏//Qt::CaseInsensitive模糊查询if (check_box->text().contains(_text, Qt::CaseInsensitive))list_widget_->item(i)->setHidden(false);elselist_widget_->item(i)->setHidden(true);}
}void MultiSelectComboBox::itemClicked(int _index)
{if (_index != 0){QCheckBox *check_box = static_cast<QCheckBox*>(list_widget_->itemWidget(list_widget_->item(_index)));check_box->setChecked(!check_box->isChecked());}
}

总结

通过这次制作下拉复选框,深入的了解了的组成。

存在问题:1、输入框不能输入中文。

2、输入框点击后,再次点击不能隐藏下拉框

3、点击item空白部分会直接隐藏下拉框

优化:样式优化,后续有时间优化后会继续更新。

如果此文帮助到你( •̀ ω •́ )✧,动动小手点个赞可好O(∩_∩)O。

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了