Dynamically fit QComboBox popup height to the (dynamically changing) count of items
-
wrote on 20 Feb 2019, 20:36 last edited by
Hi,
I have a QComboBox that can have item added/removed while the popup (item list) is shown. The issue is that the height of the popup is not changing dynamically. For example, if there were 4 item when the popup opened, if an item is added the height will stay the same but the scrollbar will appear. If an item is removed, there is a blank line at the end.
How can I make the popup always fit the content height?I have tried to call resize, repaint and update but it does not help...
-
wrote on 20 Feb 2019, 21:42 last edited by
Hi, one approach I've used: when the popup is showing and the rowcount changes, then I destroy the current QComboBox and create a new similar QComboBox in exactly the same place.
Then I call ->showPopup(); on the new one and voila, the rowcount matches the height of the popup :-) -
Hi, one approach I've used: when the popup is showing and the rowcount changes, then I destroy the current QComboBox and create a new similar QComboBox in exactly the same place.
Then I call ->showPopup(); on the new one and voila, the rowcount matches the height of the popup :-)wrote on 20 Feb 2019, 21:55 last edited by@hskoglund Could you share a snippet? How do you know if the popup is expanded or not (ie: if you have to call showPopup). And how do you place it exactly at the previous location? Does it produce some visual glitch (when the user is highlighting an item, does the box disappear and reappear visibly?)
-
wrote on 20 Feb 2019, 22:13 last edited by
I connect() to the highLighted() signal from the QComboBox (this fires for me when the popup is expanded).
To place it in exactly in the same location, I'm cheating by using a QTableWidget as a container and using ->setCellWidget() on the new QComboBox. But just copying the ->geometry() from the old QComboBox into a ->setGeometry() on the new one should suffice.
(Also you have retrieve the list items from the old QComboBox and do a ->inserItems() for them on the new one.)In my case no visual glitch is seen but you should be able to work around any glitches by doing a ->blockSignals(true); on the old and possible also the new QComboBox, and in that case when you're done restuffing the items, you could do a ->blockSignals(false);
-
I connect() to the highLighted() signal from the QComboBox (this fires for me when the popup is expanded).
To place it in exactly in the same location, I'm cheating by using a QTableWidget as a container and using ->setCellWidget() on the new QComboBox. But just copying the ->geometry() from the old QComboBox into a ->setGeometry() on the new one should suffice.
(Also you have retrieve the list items from the old QComboBox and do a ->inserItems() for them on the new one.)In my case no visual glitch is seen but you should be able to work around any glitches by doing a ->blockSignals(true); on the old and possible also the new QComboBox, and in that case when you're done restuffing the items, you could do a ->blockSignals(false);
wrote on 20 Feb 2019, 22:29 last edited by@hskoglund Your idea looks a bit complicated IMHO. I have something that might be easier but which is not yet perfect :
QFontMetrics fm(ui->comboBox->font()); int w = ui->comboBox->view()->window()->width(); int h = 2 + (fm.height()) * qMin(ui->comboBox->count(), ui->comboBox->maxVisibleItems()); ui->comboBox->view()->window()->resize(w, h);
It does not yet handle margin/padding etc, but maybe there is a way to retrieve the item height?
-
@hskoglund Your idea looks a bit complicated IMHO. I have something that might be easier but which is not yet perfect :
QFontMetrics fm(ui->comboBox->font()); int w = ui->comboBox->view()->window()->width(); int h = 2 + (fm.height()) * qMin(ui->comboBox->count(), ui->comboBox->maxVisibleItems()); ui->comboBox->view()->window()->resize(w, h);
It does not yet handle margin/padding etc, but maybe there is a way to retrieve the item height?
wrote on 20 Feb 2019, 22:41 last edited by hskoglund@AloyseTech Agree my solution is complicated, your resizing code looks good, should work too. Don't know about the item height, but perhaps divide view()->window()->height() with # of items?
Just guessing here, but couldn't you do something llke:
hidePopup(); showPopup();
to sort of "force" the QComboBox into good behavior?
Edit: perhaps with a
qApp->processEvents()
sandwiched in between them.... -
wrote on 21 Feb 2019, 09:28 last edited by
@hskoglund using hide/showPopup does not works even when using the qApp->processEvents();. I see the popup close and reopen.
-
@hskoglund using hide/showPopup does not works even when using the qApp->processEvents();. I see the popup close and reopen.
wrote on 21 Feb 2019, 11:13 last edited by@AloyseTech Sorry, nice try :-(
It's been a couple of years since I coded my solution, but I remember struggling the same way you do now. Perhaps my way of surgically removing and inserting a new QComboBox could work for you also.
-
Hi,
I have a QComboBox that can have item added/removed while the popup (item list) is shown. The issue is that the height of the popup is not changing dynamically. For example, if there were 4 item when the popup opened, if an item is added the height will stay the same but the scrollbar will appear. If an item is removed, there is a blank line at the end.
How can I make the popup always fit the content height?I have tried to call resize, repaint and update but it does not help...
@AloyseTech IIRC hidePop() will reset the Popupwidget, so maybe hijack the add/remove process.
Call hidePopup before adding are removing item and call showPopup afterwards?
1/9