4

How to make QComboBox as MultiSelect in QT ?

There is no option of MultiSelect in Combox in QT ?

OR

Anybody can suggest me some diffrent control but look & feel should be like QCombobox only.

Bokambo
  • 4,204
  • 27
  • 79
  • 130

2 Answers2

2

//This is the file named as CheckBoxList.h

#ifndef CHECKBOXLIST_H
#define CHECKBOXLIST_H

#include <QtGui>

class CheckBoxList: public QComboBox
{
    Q_OBJECT;

public:
    CheckBoxList(QWidget *widget = 0);
    virtual ~CheckBoxList();
    bool eventFilter(QObject *object, QEvent *event);
    virtual void paintEvent(QPaintEvent *);
    void SetDisplayText(QString text);
    QString GetDisplayText() const;

private:
    QString m_DisplayText;
};

#endif // CHECKBOXLIST_H

//This is the file named as CheckBoxList.cpp

#include "CheckBoxList.h"
#include <QtGui>

// internal private delegate
class CheckBoxListDelegate : public QItemDelegate
{
public:

    CheckBoxListDelegate(QObject *parent)
         : QItemDelegate(parent)
    {
        ;
    }

    void paint(QPainter *painter, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const
    {
        //Get item data
        bool value = index.data(Qt::UserRole).toBool();
        QString text = index.data(Qt::DisplayRole).toString();

        // fill style options with item data
        const QStyle *style = QApplication::style();
        QStyleOptionButton opt;
        opt.state |= value ? QStyle::State_On : QStyle::State_Off;
        opt.state |= QStyle::State_Enabled;
        opt.text = text;
        opt.rect = option.rect;

        // draw item data as CheckBox
        style->drawControl(QStyle::CE_CheckBox,&opt,painter);
//QMessageBox::information(0,"Info",text);

    }

        QWidget *createEditor(QWidget *parent,
         const QStyleOptionViewItem & option ,
         const QModelIndex & index ) const
    {
        // create check box as our editor

         QCheckBox *editor = new QCheckBox(parent);

         return editor;
    }

     void setEditorData(QWidget *editor,
                                         const QModelIndex &index) const
     {

         //set editor data
         QCheckBox *myEditor = static_cast<QCheckBox*>(editor);
         myEditor->setText(index.data(Qt::DisplayRole).toString());
         myEditor->setChecked(index.data(Qt::UserRole).toBool());

//
     }

     void setModelData(QWidget *editor, QAbstractItemModel *model,
                                        const QModelIndex &index) const
     {
         //get the value from the editor (CheckBox)
         QCheckBox *myEditor = static_cast<QCheckBox*>(editor);
         bool value = myEditor->isChecked();


         //set model data
         QMap<int,QVariant> data;
         data.insert(Qt::DisplayRole,myEditor->text());
         data.insert(Qt::UserRole,value);
         model->setItemData(index,data);

     }

     void updateEditorGeometry(QWidget *editor,
         const QStyleOptionViewItem &option, const QModelIndex &index ) const
     {

         editor->setGeometry(option.rect);


     }
 };     
//min-width:10em; 
     CheckBoxList::CheckBoxList(QWidget *widget )
     :QComboBox(widget),m_DisplayText(0)
     {
    // set delegate items view 
    view()->setItemDelegate(new CheckBoxListDelegate(this));
    //view()->setStyleSheet("  padding: 15px; ");
    // Enable editing on items view
    view()->setEditTriggers(QAbstractItemView::CurrentChanged);

    // set "CheckBoxList::eventFilter" as event filter for items view 
    view()->viewport()->installEventFilter(this);


    // it just cool to have it as defualt ;)
    view()->setAlternatingRowColors(true);
     }


CheckBoxList::~CheckBoxList()
{
    ;
}
bool CheckBoxList::eventFilter(QObject *object, QEvent *event)
{
    // don't close items view after we release the mouse button
    // by simple eating MouseButtonRelease in viewport of items view
    if(event->type() == QEvent::MouseButtonRelease && object==view()->viewport()) 
    {
        return true;
    }
    return QComboBox::eventFilter(object,event);
}
void CheckBoxList::paintEvent(QPaintEvent *)
{
    QStylePainter painter(this);
    painter.setPen(palette().color(QPalette::Text));

    // draw the combobox frame, focusrect and selected etc.
    QStyleOptionComboBox opt;
    initStyleOption(&opt);

    // if no display text been set , use "..." as default
    if(m_DisplayText.isNull())
        opt.currentText = "......";
    else
        opt.currentText = m_DisplayText;
    painter.drawComplexControl(QStyle::CC_ComboBox, opt);

    // draw the icon and text
    painter.drawControl(QStyle::CE_ComboBoxLabel, opt);

}


void CheckBoxList::SetDisplayText(QString text)
{
    m_DisplayText = text;

}

QString CheckBoxList::GetDisplayText() const
{
    return m_DisplayText;
}
Jon
  • 2,932
  • 2
  • 23
  • 30
Sudheer
  • 44
  • 1
  • How do you know which checkboxes are selected so you can generate the display text? – CompEng88 Dec 10 '15 at 21:11
  • Seems like your code has an issue when there is only 1 checkbox in the view. It seems to ignore the mouse clicks and doesn't check. I assume it as to do with the eventFilter in your combobox. Any fixes? – CompEng88 Dec 18 '15 at 23:11
  • Deriving this class from a `QComboBox` is a mistake, since you cannot properly override functionality that isn't relevant anymore, due to the functions in question not being `virtual`. – Daniel Kamil Kozar Dec 28 '16 at 08:55
0

One alternative is to set menu with checkable actions to a button, as I've shown here.
Or you can change the selection model of the combo and control the hiding and showing of the pop up window as shown here.

Community
  • 1
  • 1
zkunov
  • 3,362
  • 1
  • 20
  • 17