Dynamically fit QComboBox popup height to the (dynamically changing) count of items



  • 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...



  • 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 :-)



  • @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?)



  • 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);



  • @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?



  • @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....



  • @hskoglund using hide/showPopup does not works even when using the qApp->processEvents();. I see the popup close and reopen.



  • @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.


  • Moderators

    @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?