3

I have a ComboBox and set it to be edited.

QComboBox *myCombo = new QComboBox(this);
myCombo->setEditable(true);
myCombo->setStyleSheet("QComboBox::down-arrow{image: url(:/bulb.png);}");
myCombo->setCursor( QCursor( Qt::PointingHandCursor ) );

enter image description here

So now when i click onto the editing field, nothing happen. But what I need is, when I click onto the bulb (which is the down-arrow), something (like a table or a dialog....) should be appeared. How can I recognize this click event in this case? I looked at the list of signals for combo box but could not find any signal for that.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
songvan
  • 369
  • 5
  • 21
  • I think a possible thing is to reimplement [`showPopup()`](https://doc.qt.io/qt-5/qcombobox.html#showPopup) – thibsc Feb 27 '19 at 08:46

2 Answers2

1

By overwriting the mousePressEvent() method you must use hitTestComplexControl() method to know that QStyle::SubControl has been pressed by issuing a signal if it is QStyle::SC_ComboBoxArrow.

#include <QtWidgets>

class ComboBox: public QComboBox
{
    Q_OBJECT
public:
    using QComboBox::QComboBox;
signals:
    void clicked();
protected:
    void mousePressEvent(QMouseEvent *event) override{
        QComboBox::mousePressEvent(event);
        QStyleOptionComboBox opt;
        initStyleOption(&opt);
        QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ComboBox, &opt, event->pos(), this);
        if(sc == QStyle::SC_ComboBoxArrow)
            emit clicked();
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ComboBox w;
    w.setEditable(true);
    w.setStyleSheet("QComboBox::down-arrow{image: url(:/bulb.png);}");
    QObject::connect(&w, &ComboBox::clicked, [](){
        qDebug()<<"clicked";
    });
    w.show();
    return a.exec();
}
#include "main.moc"

Although showPopup() is a possible option this can be called directly without the down-arrow being pressed, for example by calling it directly: myCombo->showPopup() so it is not the correct option.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thank you :). I have one more small question. How can I set the mouse form for the down-arrow using this command `setCursor( QCursor( Qt::PointingHandCursor ) );` – songvan Feb 27 '19 at 11:13
  • @songvan Do you want that when the mouse is on the down-arrow change the cursor? – eyllanesc Feb 27 '19 at 11:16
  • Actually, in the code above i used `myCombo->setCursor( QCursor( Qt::PointingHandCursor ) );` (as i updated above). At the beginning when i hover the mouse over the light bulb, it is the pointing hand (as I expected). But after I clicked the light bulb, the mouse returns to the original form. How to remain the pointing hand form for the mouse permanently when I hover it over the light bulb? – songvan Feb 27 '19 at 11:20
  • @songvan I think it is impossible because what happens is that the focus goes to the popup that is a modal (behaves like a window) so if the mouse leaves the popup without closing it the owner of the cursor is the OS, and Qt can not modify it. I recommend you ask a new question and maybe others have other ideas. – eyllanesc Feb 27 '19 at 11:45
1

A possible solution is to subclass QComboBox and reimplement showPopup() virtual method:

.h:

#ifndef COMBOBOXDROPDOWN_H
#define COMBOBOXDROPDOWN_H

#include <QComboBox>
#include <QDebug>

class ComboBoxDropDown : public QComboBox
{
public:
    ComboBoxDropDown(QWidget *parent = nullptr);
    void showPopup() override;    
};

#endif // COMBOBOXDROPDOWN_H

.cpp:

#include "comboboxdropdown.h"

ComboBoxDropDown::ComboBoxDropDown(QWidget *parent)
    : QComboBox (parent)
{    
}

void ComboBoxDropDown::showPopup()
{
    //QComboBox::showPopup();
    qDebug() << "Do something";
}
thibsc
  • 3,747
  • 2
  • 18
  • 38
  • Although showPopup is a possible option, this can be called directly without the down-arrow being pressed, for example by calling it directly: `myCombo->showPopup()` – eyllanesc Feb 27 '19 at 09:04
  • @eyllanesc Yes but if he wants to show a submenu on the click, reimplement it is a good solution to trigger action without calling this method – thibsc Feb 27 '19 at 09:06
  • Well, I just want to point out the limitation of your answer since the question is very direct: *How to know when down-arrow of Combo box is **clicked**?* :-) – eyllanesc Feb 27 '19 at 09:09
  • @eyllanesc, effectively, you're right, but this virtual method is called each time you click on the "bulb", your answer is more complete ;) – thibsc Feb 27 '19 at 09:11