How to keep showing the QCombobox popup
-
Hi,
I'm writing a qcombobox to show a table in popup.
I create a QTableWidget and use setmodel(table->model()) and setView(table) to set the popup to show a table. But when I click a tableItem in this table, the popup hide automatically. I wonder how to keep showing the popup unless click the toolbutton of combobox or focus out.
Thanks. -
Hi,
Here's a suggestion:
Try using QComboBox::showPopup() by connecting it to QComboBox::activated(int index).
The behavior you're talking about is the default, and my suggestion makes it appear again when you click an item on your comboBox popup.
here's how to connect
showPopup()
toactivated()
:connect(ui->comboBox,&QComboBox::activated,ui->comboBox,&QComboBox::showPopup);
This has a problem, the popup will appear based on the activated index, meaning the activated index will be on top of the combobox instead of the first index as it normally does, here's how it looks:
To fix that, you could use
on_comboBox_activated
, and set the current index of the combo box to 0 before callingshowPopup()
:void Form::on_comboBox_activated(int index) { ui->comboBox->setCurrentIndex(0); ui->comboBox->showPopup(); }
That still leaves another problem, the popup will flicker because it's hiding and then popping up again.
I do not know how to fix that yet, one idea is to intercept the popup's hide event, but I do not know how to apply it yet.
-
Hi,
Here's a suggestion:
Try using QComboBox::showPopup() by connecting it to QComboBox::activated(int index).
The behavior you're talking about is the default, and my suggestion makes it appear again when you click an item on your comboBox popup.
here's how to connect
showPopup()
toactivated()
:connect(ui->comboBox,&QComboBox::activated,ui->comboBox,&QComboBox::showPopup);
This has a problem, the popup will appear based on the activated index, meaning the activated index will be on top of the combobox instead of the first index as it normally does, here's how it looks:
To fix that, you could use
on_comboBox_activated
, and set the current index of the combo box to 0 before callingshowPopup()
:void Form::on_comboBox_activated(int index) { ui->comboBox->setCurrentIndex(0); ui->comboBox->showPopup(); }
That still leaves another problem, the popup will flicker because it's hiding and then popping up again.
I do not know how to fix that yet, one idea is to intercept the popup's hide event, but I do not know how to apply it yet.
@Abderrahmene_Rayene Thanks for your suggestion. I'm now trying to solve the flicker problem by override the
hidePopup()
function of QCombobox with no code and use my own function to response the focus out event. But by this way, the whole ui stucked except the table just like usingexec()
which means that I even cannot focus out of the table. Perhaps there is another way to solve it. -
@Abderrahmene_Rayene Thanks for your suggestion. I'm now trying to solve the flicker problem by override the
hidePopup()
function of QCombobox with no code and use my own function to response the focus out event. But by this way, the whole ui stucked except the table just like usingexec()
which means that I even cannot focus out of the table. Perhaps there is another way to solve it.@RichardW said in How to keep showing the QCombobox popup:
I'm now trying to solve the flicker problem by override the hidePopup() function of QCombobox with no code and use my own function to response the focus out event.
Could you share exactly how you're doing that? I would like to test it on my own and see if I can work it out.
Thanks!
-
@RichardW said in How to keep showing the QCombobox popup:
I'm now trying to solve the flicker problem by override the hidePopup() function of QCombobox with no code and use my own function to response the focus out event.
Could you share exactly how you're doing that? I would like to test it on my own and see if I can work it out.
Thanks!
@Abderrahmene_Rayene sure, simply like this:
.h: class TableBox : public QComboBox { Q_OBJECT public: explicit TableBox(QWidget *parent = Q_NULLPTR); ~TableBox(); void hidePopup() override{}; // rewrite with nothing protected: bool eventFilter(QObject *obj, QEvent *event); private: QTableWidget *_listTable = nullptr; }; .cpp: TableBox::TableBox(QWidget *parent) : QComboBox(parent) { // setTable /* code to set table */ // deal with event this->view()->installEventFilter(this); } bool TableBox::eventFilter(QObject *obj, QEvent *event) { // try to hide if (obj == this->view()) { if (event->type() == QFocusEvent::FocusOut) { QCombobox::hidePopup(); } } return QObject::eventFilter(obj, event); }
in my code, the focus out event cannot reach, I have no idea why.
By the way, this method do not need to connect combobox withshowPopup()
becausehidePopup()
never actived. -
@Abderrahmene_Rayene sure, simply like this:
.h: class TableBox : public QComboBox { Q_OBJECT public: explicit TableBox(QWidget *parent = Q_NULLPTR); ~TableBox(); void hidePopup() override{}; // rewrite with nothing protected: bool eventFilter(QObject *obj, QEvent *event); private: QTableWidget *_listTable = nullptr; }; .cpp: TableBox::TableBox(QWidget *parent) : QComboBox(parent) { // setTable /* code to set table */ // deal with event this->view()->installEventFilter(this); } bool TableBox::eventFilter(QObject *obj, QEvent *event) { // try to hide if (obj == this->view()) { if (event->type() == QFocusEvent::FocusOut) { QCombobox::hidePopup(); } } return QObject::eventFilter(obj, event); }
in my code, the focus out event cannot reach, I have no idea why.
By the way, this method do not need to connect combobox withshowPopup()
becausehidePopup()
never actived.@RichardW I tried to use an eventFilter yesterday to manipulate the hide and focus events, but to no success.
Overriding
hidePopup()
with nothing caused the popup to be unable to hide, and never lose focus, unless you hit escape keybutton. It makes it act as a modal dialog or something similar, which is unwanted behavior in this case.This gave me another idea, Here it is:
void hidePopup() override { if(!listTable->geometry().contains(mapFromGlobal(QCursor::pos()))) QComboBox::hidePopup(); }
What this does is basically only prevent the comboBox popup from hiding when the cursor current position is contained within its geometry, otherwise, calls
QComboBox::hidePopup
to get the normal behavior.Be sure this does not break something else you have or cause unwanted behavior, it's a workaround.
-
@RichardW I tried to use an eventFilter yesterday to manipulate the hide and focus events, but to no success.
Overriding
hidePopup()
with nothing caused the popup to be unable to hide, and never lose focus, unless you hit escape keybutton. It makes it act as a modal dialog or something similar, which is unwanted behavior in this case.This gave me another idea, Here it is:
void hidePopup() override { if(!listTable->geometry().contains(mapFromGlobal(QCursor::pos()))) QComboBox::hidePopup(); }
What this does is basically only prevent the comboBox popup from hiding when the cursor current position is contained within its geometry, otherwise, calls
QComboBox::hidePopup
to get the normal behavior.Be sure this does not break something else you have or cause unwanted behavior, it's a workaround.
-
@Abderrahmene_Rayene Thanks for your help! I think this can be the right way to solve my problem. But this make the button of combobox not work too. Are there any method to solve this?
@RichardW said in How to keep showing the QCombobox popup:
But this make the button of combobox not work too
That's because I used the table widget geometry, just remove it from the condition, use the comboBox's geomtry instead.
void hidePopup() override { if(!geometry().contains(mapFromGlobal(QCursor::pos()))) QComboBox::hidePopup(); }
-
@RichardW said in How to keep showing the QCombobox popup:
But this make the button of combobox not work too
That's because I used the table widget geometry, just remove it from the condition, use the comboBox's geomtry instead.
void hidePopup() override { if(!geometry().contains(mapFromGlobal(QCursor::pos()))) QComboBox::hidePopup(); }
-