• Qt实现自定义多选下拉列表


    前言

    本文记录了一种通过继承 QComboBox 实现下拉列表多选功能的方法。效果如下图所示:
    在这里插入图片描述

    1、 功能描述

    普通的下拉列表只支持选择一个选项,在软件开发过程中,经常会遇到下拉列表支持选择多个选项的需求,下面的代码实现了下拉列表多选功能,支持设置弹窗的高度,支持添加显示文本和用户数据,支持设置默认选中项目,支持获取选中数据。

    2、代码实现

    2.1 头文件
    #ifndef LLCOMBOBOX_H
    #define LLCOMBOBOX_H
    
    #include 
    
    class QListWidgetItem;
    class LLComboBoxPrivate;
    class LLComboBox : public QComboBox
    {
        Q_OBJECT
    public:
        explicit LLComboBox(QWidget* parent = NULL);
    
        /**
         * @brief addDataItem 添加数据
         * @param text
         * @param userData
         */
        void addDataItem(const QString &text, const QVariant &userData = QVariant());
    
        /**
         * @brief setSelectedData 设置选中的数据
         * @param selectedData
         */
        void setSelectedData(const QStringList &selectedData);
    
        /**
         * @brief setPopupViewHeight 设置下拉列表弹窗的高度,默认值100
         * @param height
         */
        void setPopupViewHeight(int height);
    
        /**
         * @brief selectedDataText 获取选择的数据
         * @return
         */
        QStringList selectedDataText();
    
        /**
         * @brief selectedUserData 获取选择数据对应的用户数据
         * @return
         */
        QList<QVariant> selectedUserData();
    
    private slots:
        void slot_itemChanged(QListWidgetItem *item);
    private:
    
        LLComboBoxPrivate *m_pd;
    };
    
    #endif // LLCOMBOBOX_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    2.2 源码文件
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include "llcombobox.h"
    
    class LLComboBoxPrivate
    {
    public:
    
        QStringList selectedDataList;
        QListWidget *pListWidget;
    };
    
    LLComboBox::LLComboBox(QWidget *parent)
        : QComboBox(parent)
        , m_pd(new LLComboBoxPrivate)
    {
        m_pd->pListWidget = new QListWidget;
        m_pd->pListWidget->setFixedHeight(100);
        connect(m_pd->pListWidget, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(slot_itemChanged(QListWidgetItem *)));
        setView(m_pd->pListWidget);
        //设置Editable为true,lineEdit() 函数才不返回空
        setEditable(true);
    }
    
    void LLComboBox::addDataItem(const QString &text, const QVariant &userData)
    {
        m_pd->pListWidget->blockSignals(true);
        QListWidgetItem *pItem = new QListWidgetItem(text, m_pd->pListWidget);
        pItem->setData(Qt::UserRole, userData);
        pItem->setCheckState(Qt::Unchecked);
        //设置QListWidgetItem 可交互且可以选中和取消选中
        pItem->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
        QComboBox::addItem(text);
        QComboBox::setCurrentText("");
        m_pd->pListWidget->blockSignals(false);
    }
    
    void LLComboBox::setSelectedData(const QStringList &selectedData)
    {
        m_pd->selectedDataList.clear();
        m_pd->selectedDataList += selectedData;
    
        QString text = "";
        for (int var = 0; var < m_pd->selectedDataList.size(); ++var)
        {
            m_pd->pListWidget->blockSignals(true);
            QListWidgetItem *pItem = m_pd->pListWidget->item(var);
            pItem->setCheckState(Qt::Checked);
            m_pd->pListWidget->blockSignals(false);
    
            text.append(m_pd->selectedDataList[var]);
            if(var < m_pd->selectedDataList.size() - 1)
            {
                text.append(",");
            }
        }
    
        lineEdit()->setText(text);
    }
    
    QStringList LLComboBox::selectedDataText()
    {
        return m_pd->selectedDataList;
    }
    
    QList<QVariant> LLComboBox::selectedUserData()
    {
        QList<QVariant> dataList;
        for (int var = 0; var < m_pd->selectedDataList.size(); ++var)
        {
            QListWidgetItem *pItem = m_pd->pListWidget->item(var);
            if(pItem->checkState() == Qt::Checked)
            {
                dataList.append(pItem->data(Qt::UserRole));
            }
        }
    
        return dataList;
    }
    
    void LLComboBox::slot_itemChanged(QListWidgetItem *item)
    {
        qDebug() << QString("text=") << item->text();
        if(m_pd->selectedDataList.contains(item->text()))
        {
            m_pd->selectedDataList.removeOne(item->text());
        }
        else
        {
            m_pd->selectedDataList.append(item->text());
        }
    
        QString text = "";
        for (int var = 0; var < m_pd->selectedDataList.size(); ++var)
        {
            text.append(m_pd->selectedDataList[var]);
            if(var < m_pd->selectedDataList.size() - 1)
            {
                text.append(",");
            }
        }
    
        lineEdit()->setText(text);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    2.3 设计思路

    本控件继承自QComboBox,重新设置了QComboBox的弹出列表为 QListWidget 的实例pListWidget。当添加下拉列表元素时先创建一个QListWidgetItem,并通过setFlags 函数设置为可交互且用户可点击,通过setCheckState函数设置默认为非选中状态。需要注意的是必须调用 QComboBox::addItem(); 方法向QComboBox 添加数据,弹窗才能正常显示。

    通过QListWidget 的 itemChanged(QListWidgetItem *)信号来判断一个选项是否选中,因此在添加数据前要先阻塞pListWidget的信号发送,添加结束后再开启信号发送。可以看到添加数据的代码是写在blockSignals();之间的。

    	m_pd->pListWidget->blockSignals(true);
        //添加多选列表数据
        m_pd->pListWidget->blockSignals(false);
    
    • 1
    • 2
    • 3

    QComboBox默认只显示一个选中的选项,为了显示选择的多个选项数据,这里设置QComboBox为可编辑,这样lineEdit()函数将返回编辑框指针,我们将多选的数据拼接起来设置到lineEdit中。如果不设置QComboBox为可编辑,lineEdit()函数将返回空指针。

    3、示例

    在测试工程中,找一个UI,拖一个QComboBox组件到布局中,并将其提升为LLComboBox,如下图所示

    在这里插入图片描述

    在对应的cpp文件中,加入下面的测试代码

    void TableWidgetTest::initComboBox()
    {
        QStringList dataList;
        dataList << QString("语文") << QString("数学") << QString("英语") << QString("物理")
                 << QString("化学") << QString("政治") << QString("体育") << QString("音乐");
        for (int var = 0; var < dataList.size(); ++var)
        {
            ui->comboBox->addDataItem(dataList[var]);
        }
    
        QStringList seledataList;
        seledataList << QString("语文") << QString("数学");
        ui->comboBox->setSelectedData(seledataList);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    编译运行程序,查看效果。

    4、总结

    以上就是本文的所有内容了,欢迎留言讨论,源码下载地址 多选下拉列表下载地址

  • 相关阅读:
    Word自动生成目录的方法
    uni-app多次触发事件,防止重复点击
    JVM运行时数据区域详解
    clion qt导出dll给别的项目用
    NLP时政有害信息的界定
    技术人员转岗产品经理,有优势吗?
    eNSP - PIM 查看命令
    vue3前端开发-flex布局篇
    vue使用scope插槽实现dialog窗口
    2 找出从指定结点出发且长度为m的所有简单路径---来源舒姐
  • 原文地址:https://blog.csdn.net/zheng19880607/article/details/133194574