0


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

文章目录


本系列目录

Qt 下拉复选框(MultiSelectComboBox)(一) 实现下拉框多选,搜索下拉框内容
Qt 下拉复选框(MultiSelectComboBox)(二) 样式表设置
Qt 下拉复选框(MultiSelectComboBox)(三) 不能输入中文等问题修复


前言

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

在这里插入图片描述


参考博客地址:https://blog.csdn.net/u013135921/article/details/79437392
以下是本篇文章正文内容,主要实现功能,下面案例可供参考

一、QCombobox的组成

  QComboBox类对象由三部分组成:QLineEdit、QToolButton、QListWidget。
在这里插入图片描述

  • QLineEdit负责选中选项的显示,由此要设置为不可编辑状态。
  • QToolButton是一个弹出与隐藏下拉框的按钮。
  • QListWidget是最重要的一部分,所有选项内容显示的格式,自定义功能的添加主要都集中在这部分。

二、MultiSelectComboBox实现

1. 总体实现

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

代码如下(示例):

this->setView(list_widget_);this->setLineEdit(line_edit_);
  • line_edit_部分用来显示选择的结果和弹出下拉框,显示内容使用 “;” 进行分割
  • list_widget_下拉框部分,显示搜索框与选项。QListWidget类对象可以通过设置Item,在item中添加QWidget对象来实现一些特殊功能。这里的list_widget_,搜索框为QlineEdit类对象,用户输入搜索条件后显示符合条件的选项,用来解决选项过多的问题,选项为QCheckBox类对象,有“选中”和“未选中”两种状态。

2. QLineEdit部分

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

代码如下(示例):

/*设置文本框*///设为只读,因为该输入框只用来显示选中的选项,称为文本框更合适些
    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();returntrue;}returnfalse;}

3. QListWidget部分

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

1. 搜索框部分

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

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

/*设置搜索框*/
    QListWidgetItem* currentItem =newQListWidgetItem(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&)));
voidMultiSelectComboBox::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);else
            list_widget_->item(i)->setHidden(true);}}

2. 选项部分

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

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

connect(checkbox,&QCheckBox::stateChanged,this,&MultiSelectComboBox::stateChange);
voidMultiSelectComboBox::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. 对外接口定义

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

接口定义如下(示例):

//隐藏下拉框
    virtual voidhidePopup();//添加一条选项voidaddItem(const QString& _text,const QVariant& _variant =QVariant());//添加多条选项voidaddItems(const QStringList& _text_list);//返回当前选中选项
    QStringList currentText();//返回当前选项条数
    int count()const;//设置搜索框默认文字voidSetSearchBarPlaceHolderText(const QString _text);//设置文本框默认文字voidSetPlaceHolderText(const QString& _text);//下拉框状态恢复默认(所有选项都恢复为未选中状态)voidResetSelection();//清空所有内容(选项内容全部清空)voidclear();//文本框内容清空(选项内容不清空,所有选项都恢复为未选中状态,文本框清空)voidTextClear();//设置选中文本--单voidsetCurrentText(const QString& _text);//设置选中文本--多voidsetCurrentText(const QStringList& _text_list);//设置搜索框是否禁用voidSetSearchBarHidden(bool _flag);

5. 代码实现

头文件:

#pragma once

#include <QComboBox>
#include <QListWidget>
#include <QLineEdit>
#include <QCheckBox>
#include <QEvent>classMultiSelectComboBox:public QComboBox
{Q_OBJECTpublic:MultiSelectComboBox(QWidget *parent =Q_NULLPTR);~MultiSelectComboBox();//隐藏下拉框
    virtual voidhidePopup();//添加一条选项voidaddItem(const QString& _text,const QVariant& _variant =QVariant());//添加多条选项voidaddItems(const QStringList& _text_list);//返回当前选中选项
    QStringList currentText();//返回当前选项条数
    int count()const;//设置搜索框默认文字voidSetSearchBarPlaceHolderText(const QString _text);//设置文本框默认文字voidSetPlaceHolderText(const QString& _text);//下拉框状态恢复默认voidResetSelection();//清空所有内容voidclear();//文本框内容清空voidTextClear();//设置选中文本--单voidsetCurrentText(const QString& _text);//设置选中文本--多voidsetCurrentText(const QStringList& _text_list);//设置搜索框是否禁用voidSetSearchBarHidden(bool _flag);protected://事件过滤器
    virtual bool eventFilter(QObject *watched,QEvent *event);//滚轮事件
    virtual voidwheelEvent(QWheelEvent *event);//按键事件
    virtual voidkeyPressEvent(QKeyEvent *event);privateslots://槽函数:文本框文本变化voidstateChange(int _row);//槽函数:搜索框文本变化voidonSearch(const QString& _text);//槽函数:点击下拉框选项voiditemClicked(int _index);signals://信号:发送当前选中选项voidselectionChange(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_ =newQListWidget();
    line_edit_ =newQLineEdit();
    search_bar_ =newQLineEdit();/*设置搜索框*/
    QListWidgetItem* currentItem =newQListWidgetItem(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(){}voidMultiSelectComboBox::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();}}voidMultiSelectComboBox::addItem(const QString& _text,const QVariant& _variant /*= QVariant()*/){Q_UNUSED(_variant);
    QListWidgetItem* item =newQListWidgetItem(list_widget_);
    QCheckBox* checkbox =newQCheckBox(this);
    checkbox->setText(_text);
    list_widget_->addItem(item);
    list_widget_->setItemWidget(item, checkbox);connect(checkbox,&QCheckBox::stateChanged,this,&MultiSelectComboBox::stateChange);}voidMultiSelectComboBox::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;}voidMultiSelectComboBox::SetSearchBarPlaceHolderText(const QString _text){
    search_bar_->setPlaceholderText(_text);}voidMultiSelectComboBox::SetPlaceHolderText(const QString& _text){
    line_edit_->setPlaceholderText(_text);}voidMultiSelectComboBox::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);}}voidMultiSelectComboBox::clear(){
    line_edit_->clear();
    list_widget_->clear();
    QListWidgetItem* currentItem =newQListWidgetItem(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&)));}voidMultiSelectComboBox::TextClear(){
    line_edit_->clear();ResetSelection();}voidMultiSelectComboBox::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);}}voidMultiSelectComboBox::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);}}voidMultiSelectComboBox::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();returntrue;}returnfalse;}voidMultiSelectComboBox::wheelEvent(QWheelEvent *event){//禁用QComboBox默认的滚轮事件Q_UNUSED(event);}voidMultiSelectComboBox::keyPressEvent(QKeyEvent *event){QComboBox::keyPressEvent(event);}voidMultiSelectComboBox::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);}voidMultiSelectComboBox::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);else
            list_widget_->item(i)->setHidden(true);}}voidMultiSelectComboBox::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());}}

总结

通过这次制作下拉复选框,深入的了解了QComboBox的组成。
存在问题:1、输入框不能输入中文。
2、输入框点击后,再次点击不能隐藏下拉框
3、点击item空白部分会直接隐藏下拉框
优化:样式优化,后续有时间优化后会继续更新。

如果此文帮助到你( •̀ ω •́ )✧,动动小手点个赞可好O(∩_∩)O。
原创文章,转载请标明本文出处。

标签: qt 开发语言 c++

本文转载自: https://blog.csdn.net/qq_43793182/article/details/122080407
版权归原作者 梦醒梦起 所有, 如有侵权,请联系我们删除。

“Qt 下拉复选框(MultiSelectComboBox)(一) 实现下拉框多选,搜索下拉框内容”的评论:

还没有评论