Search code examples
pythonpyqt5qcombobox

How to stop spacebar popup qcombobox in python


By default qcombobox performs inline autocompletion and this is working fine but when the item contains a space the spacebar keypress popup the qcombobox how can i disable this and let the space key used in the inline autocompletion i have tried using complete with this code

self.ui.comboBox_ui_3.setEditable(True)
self.ui.comboBox_ui_3.completer().setCompletionMode(QCompleter.InlineCompletion)
self.ui.comboBox_ui_3.setInsertPolicy(QComboBox.NoInsert)

but this is not performing as expected as it allows user in enter letters in the editable line thats not in your list


Solution

  • When the spacebar is pressed, the keyPressEvent of QComboBox is called, and if it is not editable it automatically shows the popup (the same happens with F4 and Alt+↓). If another key is pressed and that key is not used for "keyboard navigation" such as the arrow keys, the keyboard search (not "autocompletion", which is a completely different thing) is activated.

    Keyboard search uses the keyboardSearch() function of the popup, so the solution is to implement a similar method.

    This can be achieved with a subclass:

    class MyCombo(QtWidgets.QComboBox):
        def keyPressEvent(self, event):
            if event.key() == QtCore.Qt.Key_Space:
                # get the QModelIndex of the underlying model
                currentModelIndex = self.model().index(
                    self.currentIndex(), self.modelColumn(), self.rootModelIndex())
                # get the popup view, which uses the same model
                view = self.view()
                # set the model index on the view
                view.setCurrentIndex(currentModelIndex)
                # call the keyboard search with the space character
                view.keyboardSearch(' ')
            else:
                # use the default implementation if any other key is pressed
                super().keyPressEvent(event)
    

    Since you are probably using an UI generated by designer, the easiest solution would be to install an event filter on the combo. The implementation is almost the same.

    class MyWindow(QtWidgets.QMainWindow):
        def __init__(self):
            # ...
            self.ui.comboBox_ui_3.installEventFilter(self)
    
        def eventFilter(self, source, event):
            if source == self.ui.comboBox_ui_3 and event.type() == event.KeyPress:
                if event.key() == QtCore.Qt.Key_Space:
                    currentModelIndex = source.model().index(
                        source.currentIndex(), source.modelColumn(), source.rootModelIndex())
                    view = source.view()
                    view.setCurrentIndex(currentModelIndex)
                    view.keyboardSearch(' ')
                    return True
            return super().eventFilter(source, event)