Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QComboBox::showPopup() override timing problem



  • I override http://doc.qt.io/qt-5/qcombobox.html#showPopup (called when user clicks the combo's dropdown button) to execute some code to populate the list of items shown dynamically, prior to displaying the list.

    It seems this works well if the population code executed is "quick" but misbehaves if the code is "slow" by failing to actually show the popup after population.

    Following code tested with Qt 5.7 under Linux. I cannot test under Windows, so I don't know if the issue is Qt widget or native combobox.

    class JComboBox(QComboBox):
        # class variable for a new "popupAboutToBeShown" signal
        # Qt does not emit a signal when the dropdwon/popup of a combobox is about to be shown
        # we add this signal, which can be used for e.g. dynamically populating the items
        popupAboutToBeShown = QtCore.pyqtSignal(name='popupAboutToBeShown')
    
        # override of virtual function
        def showPopup(self):
            # emit the new signal
            self.popupAboutToBeShown.emit()
            # call the base method now to display the popup
            super().showPopup()
    

    I do not believe the issue is to do with the use of signal/slot here, but that is how I do it. All single-threaded here, the emit() is indeed a direct, blocking function call to slot. [EDIT I just tried code below in direct override of showPopup() instead of going via signal/slot to eliminate that, same behaviour.]

    self.combo = JCombBox()
    self.combo.setEditable(True)
    self.combo.popupAboutToBeShown.connect(populateCombo)
    
    def populateCombo(self)
        # In real life `items` would be populated by call to synchronous, non-Qt library function
        # which takes a little time to complete
        # Here we emulate this with a "sleep" and a fixed list
        # QThread.msleep(100)    # this works
        QThread.msleep(500)    # this misbehaves
        items = ["Item 1", "Item 2", "Item 3"]
        self.combo.clear()
        self.combo.addItems(items)
    

    In my tests, after a delay of 100 millis the popup is shown with its new items. However, with a delay of 500 millis the popup does not get shown (the items are correctly populated, e.g. can be seen by using the down arrow key on the combo to move through them). Obviously your mileage may vary on the numbers for the delay.

    Any comment on how long my showPopup() is allowed to take before something decides it's not going to show the popup/dropdown list?

    At this rate I'm thinking I won't be able to override showPopup to dynamically populate list (something which I have done successfully in native Windows code in the past) and will have to rewrite so that I have something like a ... button with an attached popup dialog instead to execute the code because I can't do it right via a QComboBox, which is doable but would be a shame....


  • Lifetime Qt Champion

    Hi
    Tested on windows.
    Seems to work as expected.
    alt text

    class ComboTest : public QComboBox {
      Q_OBJECT
     public:
      explicit ComboTest(QWidget* parent = nullptr);
     public slots:
     public:
      virtual void showPopup() override {
        clear();
        for (int var = 0; var < 10000; ++var) {
          addItem("TEST" + QString::number(var));
        }
        QComboBox::showPopup();
      }
    };
    

    Takes quite some time for it to open. but seems to do it every time.



  • @mrjj
    Thank you for testing. But to test same as me, please replace with something like

      virtual void showPopup() override {
        QThread::msleep(2000);
        clear();
        for (int var = 0; var < 3; ++var) {
          addItem("TEST" + QString::number(var));
        }
        QComboBox::showPopup();
      }
    

    If that still works for you, I guess it's something like Ubuntu desktop (Unity)/X11 which is interfering (or my Qt 5.7 if you're on later).


  • Lifetime Qt Champion

    @JonB
    Hi still works with msleep.
    Im on Qt.5.11.1
    update: installing 5.7 just to see.
    will report back when its finished.



  • @mrjj
    Hmm, thank you for testing. I guess it must be either my Linux or my Qt 5.7 then....

    I'll leave this open for a while, in case e.g. someone wishes to test your code under Linux/Qt 5.7.

    Meanwhile since I need to support my configuration I'm already doing it via a separate button to refresh combo list instead. I'll have to stick with that if I cannot resolve showPopup()....


  • Lifetime Qt Champion

    @JonB
    Works the same in Qt5.7
    ill try on linux a later.


Log in to reply