ldlchina
ldlchina

Reputation: 955

QComboBox: Can we make the entire combobox clickable, not just the dropdown button (arrow) itself?

I want to show a text like "Please select one option" on the combobox, and don't show the text in the list, so I set setEditable to true, then set the text to the lineEdit, but after this, only the dropdown button (arrow) is clickable, how can we make the entire combobox clickable? I'm using the QComboBox as below:

QComboBox* combbox= new QComboBox;
combbox->setEditable(true);
combbox->lineEdit()->setReadOnly(true);
combbox->addItem("Option1");
combbox->addItem("Option2");
combbox->lineEdit()->setText("Please select one option");

Upvotes: 1

Views: 3091

Answers (4)

Jeruntu
Jeruntu

Reputation: 188

The answer from IdlChina has one drawback: when you click the combobox when it's already shown, it hides and immediately shows again. I have a slightly different approach that doesn't have that problem.

class ButtonComboBox : public QComboBox
{
public:
    ButtonComboBox(QWidget *parent = nullptr)
        : QComboBox(parent),
          _isPopupShown(false),
          _timer(new QTimer(this))
    {
        auto lineEdit = new QLineEdit;
        lineEdit->installEventFilter(this);
        setLineEdit(lineEdit);

        _timer->setSingleShot(true);
        _timer->setInterval(100);
    }

protected:
    bool eventFilter(QObject *object, QEvent *event) override
    {
        if (object == lineEdit() && event->type() == QEvent::MouseButtonPress) {
            if (!_timer->isActive()) {
                if (!_isPopupShown)
                    showPopup();
                else if (_isPopupShown)
                    hidePopup();

                return true;
            }
        }

        return false;
    }

    void showPopup() override
    {
        QComboBox::showPopup();
        _isPopupShown = true;
        _timer->start();
    }

    void hidePopup() override
    {
        QComboBox::hidePopup();
        _isPopupShown = false;
        _timer->start();
    }

private:
    bool _isPopupShown;
    QTimer *_timer;
};

Upvotes: 0

ldlchina
ldlchina

Reputation: 955

I resolved this problem as below:

class QTComboBoxButton : public QLineEdit
{
    Q_OBJECT
public:
    QTComboBoxButton(QWidget *parent = 0);
    ~QTComboBoxButton();

protected:
    void mousePressEvent(QMouseEvent *);
};

QTComboBoxButton::QTComboBoxButton(QWidget *parent /* = 0 */) :
    QLineEdit(parent)
{
}

QTComboBoxButton::~QTComboBoxButton()
{
}

void QTComboBoxButton::mousePressEvent(QMouseEvent * e)
{
    QComboBox* combo = dynamic_cast<QComboBox*>(parent());
    if(combo)
        combo->showPopup();
}

QComboBox* combbox= new QComboBox;
combbox->setEditable(true);
combbox->setLineEdit(new QTComboBoxButton(combbox));
combbox->lineEdit()->setReadOnly(true);
combbox->addItem("Option1");
combbox->addItem("Option2");
combbox->lineEdit()->setText("Please select one option");

Upvotes: 3

Julien Vatsana
Julien Vatsana

Reputation: 31

You can use this lib : libqxt

You can find it here : https://bitbucket.org/libqxt/libqxt/wiki/Home

Use the object QxtCheckComboBox, with it you can check multiple items in your ComboBox.

Upvotes: 0

Sommerwild
Sommerwild

Reputation: 549

Making a QComboBox editable is problematic in terms of UI. I propose a different approach, reimplement a QComboBox and make a default item and remove it if the user clicks the combobox:

#include "mycombo.h"

MyCombo::MyCombo(QWidget *parent) :
    QComboBox(parent),
    defaultText_("Please select one option")
{
    addItem(defaultText_);
}

void MyCombo::mousePressEvent(QMouseEvent* event)
{
    if(this->currentText() == defaultText_)
    {
        this->removeItem(0);
    }

    QComboBox::mousePressEvent(event);
}

And then just create this combobox and insert the items where you want

MyCombo *combbox = new MyCombo(this);
combbox->addItem("Option1");
combbox->addItem("Option2");

Upvotes: 0

Related Questions