When opening a combox box, always have the first item pre-highlighted and lcoated under the mouse
-
Hello,
I have a combo box with the following entries : All, 1, 2, 3, ...., 25.
As part of the normal usage of the combo box (and, in general, the app I am working on) the user may hop around between 1 and 25 at random (no specific order, they describe totally independent objects).
However, very often, he will want to go back to "All".
I noticed that after selecting integer N for example, the combo box will always open to be centered around that value. Could I instead say "Please show the combo box with entry 'All' under the mouse, highlighted and ready to go, at all times ?".
Like I said, it doesn't matter anyways that N is what is currently under the mouse, as nearby values like N-1 or N+1 are not more interesting than any other value, and have no more chances than any other value of being the next one selected. Rather, the most likely choice when the user opens the combo box is always "All".
Here is what it looks like with value 8 selected, before opening the combo box :
And here it is after having clicked on the combo box and opened it :
-
I have found a simple solution that almost works perfectly. I subclassed
QComboBox
like this :class MyComboBox : public QComboBox { Q_OBJECT public: explicit MyComboBox (QWidget* parent = nullptr) : QComboBox(parent) {} virtual ~MyComboBox () {} void showPopup() { /* Just before opening the combo box, * save the current state and instead pre-select index 0. */ m_tmpIndex = this->currentIndex(); this->setCurrentIndex(0); QComboBox::showPopup(); } void hidePopup() { QComboBox::hidePopup(); /* Upon closing the combo box, * If the user has actively selected an index other than 0, * Use that index. * If not (e.g. user clicked outside the combo box to close it, * without selecting an index) * then re-establish the index as it was before opening the combo box. * */ if(this->currentIndex() == 0) { this->setCurrentIndex(m_tmpIndex); } } private: int m_tmpIndex; };
Now all it takes a is a double click on the combo box to have index 0 "All" selected. However the double click needs to be slow i.e. with a lot of time between each click. Why is that ?
-
I have found a simple solution that almost works perfectly. I subclassed
QComboBox
like this :class MyComboBox : public QComboBox { Q_OBJECT public: explicit MyComboBox (QWidget* parent = nullptr) : QComboBox(parent) {} virtual ~MyComboBox () {} void showPopup() { /* Just before opening the combo box, * save the current state and instead pre-select index 0. */ m_tmpIndex = this->currentIndex(); this->setCurrentIndex(0); QComboBox::showPopup(); } void hidePopup() { QComboBox::hidePopup(); /* Upon closing the combo box, * If the user has actively selected an index other than 0, * Use that index. * If not (e.g. user clicked outside the combo box to close it, * without selecting an index) * then re-establish the index as it was before opening the combo box. * */ if(this->currentIndex() == 0) { this->setCurrentIndex(m_tmpIndex); } } private: int m_tmpIndex; };
Now all it takes a is a double click on the combo box to have index 0 "All" selected. However the double click needs to be slow i.e. with a lot of time between each click. Why is that ?
@SuperSelrak
Be aware that if you have a slot on current index/text changed that will fire during bothshowPopup()
andhidePopup()
. Also the user can now never select the "All" item #0 once he has selected another item, is that not an issue? -
@SuperSelrak
Be aware that if you have a slot on current index/text changed that will fire during bothshowPopup()
andhidePopup()
. Also the user can now never select the "All" item #0 once he has selected another item, is that not an issue?@JonB Thank you for the reminder about the signal that will fire. I actually only care about the
activate
signal which gets fired only when the index or text has been changed by actual user interaction (and not by program like in the code I wrote for my subclass).However no, the other problem you mention does not happen. I don't see why it would, either.
Also, because of this delay I noticed, I added another good method : use buttons of the mouse ! This is pretty much available on all mice nowadays.
void mousePressEvent(QMouseEvent * event) { if((event->button() == Qt::MiddleButton) || (event->button() == Qt::RightButton)) { this->setCurrentIndex(0); this->activated(0); } else { QComboBox::mousePressEvent(event); } }
-
@JonB Thank you for the reminder about the signal that will fire. I actually only care about the
activate
signal which gets fired only when the index or text has been changed by actual user interaction (and not by program like in the code I wrote for my subclass).However no, the other problem you mention does not happen. I don't see why it would, either.
Also, because of this delay I noticed, I added another good method : use buttons of the mouse ! This is pretty much available on all mice nowadays.
void mousePressEvent(QMouseEvent * event) { if((event->button() == Qt::MiddleButton) || (event->button() == Qt::RightButton)) { this->setCurrentIndex(0); this->activated(0); } else { QComboBox::mousePressEvent(event); } }
@SuperSelrak said in When opening a combox box, always have the first item pre-highlighted and lcoated under the mouse:
However no, the other problem you mention does not happen. I don't see why it would, either.
if(this->currentIndex() == 0) { this->setCurrentIndex(m_tmpIndex); }
in
hidePopup()
. So if duringshowPopup()
something other than "All" was selected, while the popup is visible the user clicks "All" and then thishidePopup()
gets called, won't that revert the current index to them_tmpIndex
that was saved fromshowPopup()
?