自定义带复选框QComboBox,包括代理

文章介绍了一个名为WComboBox的类,它扩展了QComboBox以添加复选框功能,并能在ComboBox中实时显示选中内容。WComboBoxDelegate是一个代理类,用于在Model-View框架中自定义表格单元格,特别是将某一列编辑状态转换为这种带有复选框的ComboBox。类提供了添加项、设置选中项的方法,并处理了激活事件来更新显示文本。
摘要由CSDN通过智能技术生成

工作中不乏这样一个需求:给ComboBox加上复选框,并且可以实时显示勾选内容。

扩展到Model-View框架中就形成了一个代理,对单元格中的内容进行自定义。

效果如图:

#ifndef WCOMBOBOXDELEGATE_H
#define WCOMBOBOXDELEGATE_H
#include <QDebug>
#include <QComboBox>
#include <QListView>
#include <QLineEdit>
#include <QItemDelegate>
#include <QAbstractItemView>
#include <QStandardItemModel>

/**
 * @brief The WComboBox class
 * @author wanghp
 * 提供一个代理类,可以将表格某列编辑态变为有复选框的选择控件comboBox
 * 还有部分问题被绕过,可以正常使用,未来修复
 */

class WComboBox : public QComboBox
{
    Q_OBJECT
public:
    WComboBox(QWidget *parent = nullptr)
        : QComboBox (parent)
    {
        m_lineEdit = new QLineEdit();
        m_lineEdit->setReadOnly(true);
        m_listView = new QListView();
        m_model = new QStandardItemModel();
        this->setLineEdit(m_lineEdit);
        this->setView(m_listView);
        this->setModel(m_model);
        connect(this, SIGNAL(activated(int)), this, SLOT(slot_activated(int)));
    }

    void addItems(const QStringList &labels)
    {
        for(auto i: labels)
        {
            QStandardItem *item = new QStandardItem(i);
            item->setCheckState(Qt::Unchecked);
            m_model->appendRow(item);
        }
    }

    void setChecked(const QStringList &checkedList)
    {
        for(int i = 0; i < m_model->rowCount(); i ++)
        {
            QString curText = m_model->item(i)->text();
            if(checkedList.contains(curText))
            {
                m_model->item(i)->setCheckState(Qt::Checked);
            }
        }
    }

protected:
    void hidePopup()
    {
        int width = this->view()->width();
        int height = this->view()->height();
        QRect rect(0, this->height(), width, height);
        int x = QCursor::pos().x() - mapToGlobal(this->geometry().topLeft()).x() + this->geometry().x();
        int y = QCursor::pos().y() - mapToGlobal(this->geometry().topLeft()).y() + this->geometry().y();
        if(!rect.contains(x, y))
        {
            QComboBox::hidePopup();
        }
    }

private:
    void updateText()
    {
        QStringList checkedLabels;
        for(int i = 0; i < m_model->rowCount(); i ++)
        {
            if(m_model->item(i)->checkState() == Qt::Checked)
            {
                checkedLabels.append(m_model->item(i)->text());
            }
        }
        m_lineEdit->setText(checkedLabels.join(","));
        m_lineEdit->setToolTip(checkedLabels.join(","));
    }

private slots:
    void slot_activated(int index)
    {
        QStandardItem *cur_item = m_model->item(index);
        if(!cur_item) return;

        Qt::CheckState state = cur_item->checkState() == Qt::Unchecked ? Qt::Checked : Qt::Unchecked;
        cur_item->setCheckState(state);

        updateText();
    }

private:
    QLineEdit *m_lineEdit;
    QListView *m_listView;
    QStandardItemModel *m_model;
};

class WComboBoxDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    WComboBoxDelegate(QObject *parent = nullptr)
        : QItemDelegate(parent) { }

    void setItems(const QStringList &texts) { _texts = texts; }

public:
    QWidget *createEditor(QWidget *parent,
                          const QStyleOptionViewItem &option,
                          const QModelIndex &index) const override
    {
        WComboBox *editor = new WComboBox(parent);
        editor->addItems(_texts);
        QStringList text = index.model()->data(index, Qt::DisplayRole).toString().split(",");
        if(text.count() > 1)
        {
            editor->setChecked(text);
        }
        else if(text.count() == 1 && text.at(0) == editor->itemText(0))
        {
            editor->setChecked(text);
        }
        return editor;
    }

    void setEditorData(QWidget *editor, const QModelIndex &index) const override
    {
        QStringList text = index.model()->data(index, Qt::EditRole).toStringList();
        WComboBox *comboBox = static_cast<WComboBox*>(editor);
        if(text.count() > 1)
        {
            comboBox->setCurrentText(text.join(","));
            comboBox->setChecked(text);
        }
        else if(text.count() == 1)
        {
            if(text.at(0) == comboBox->itemText(0))
            {

            }
            else
            {
                comboBox->setCurrentText(text.at(0));
            }
        }
    }

    void setModelData(QWidget *editor,
                      QAbstractItemModel *model,
                      const QModelIndex &index) const override
    {
        WComboBox *comboBox = static_cast<WComboBox*>(editor);
        QString text = comboBox->currentText();
        model->setData(index, text, Qt::EditRole);
        qDebug() << "setModelData: " << text << endl;
    }

    void updateEditorGeometry(QWidget *editor,
                               const QStyleOptionViewItem &option,
                               const QModelIndex &index) const override
    {
        editor->setGeometry(option.rect);
    }

private:
    QStringList _texts;
};

#endif // WCOMBOBOXDELEGATE_H

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值