pythonpyqtpyqt5qlineeditqcompleter

python GUI autocomplete by key value


I am trying to create an autocomplete GUI in python such that as I type a first name, I see possible last names. For example, let's say I have this dictionary: {"George": ["Washington", "Bush"]}. When I start typing "G", I want it to show "Washington" and "Bush". When "Washington" is selected, I want "Washington" to show. I am new to GUIs and I think PyQt has an example of autocompletion, but the words are not in key value pairs but a list of words. https://wiki.python.org/moin/PyQt/Adding%20auto-completion%20to%20a%20QLineEdit

Is there a way to edit the code in the link so that I can enable this feature? Thank you!


Solution

  • You have to override the pathFromIndex method so that when you select some text, the appropriate option is written in the QLineEdit, and to change what is shown in the popup a delegate should be used.

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    def create_model(d):
        model = QtGui.QStandardItemModel()
        for key, value in d.items():
            for val in value:
                it = QtGui.QStandardItem(key)
                it.setData(val, QtCore.Qt.UserRole)
                model.appendRow(it)
        return model
    
    class StyledItemDelegate(QtWidgets.QStyledItemDelegate):
        def initStyleOption(self, option, index):
            super(StyledItemDelegate, self).initStyleOption(option, index)
            option.text = index.data(QtCore.Qt.UserRole)
    
    class Completer(QtWidgets.QCompleter):
        def __init__(self, parent=None):
            super(Completer, self).__init__(parent)
            QtCore.QTimer.singleShot(0, self.change_delegate)
    
        @QtCore.pyqtSlot()
        def change_delegate(self):
            delegate = StyledItemDelegate(self)
            self.popup().setItemDelegate(delegate)
    
        def pathFromIndex(self, index):
            return index.data(QtCore.Qt.UserRole)
    
    if __name__ == '__main__':
        import sys
        app = QtWidgets.QApplication(sys.argv)
        d = {
            "George": ["Washington", "Bush"],
            "Languages": ["Python", "C++"]
        }
        model = create_model(d)
        w = QtWidgets.QLineEdit()
        completer = Completer(w)
        completer.setModel(model)
        w.setCompleter(completer)
        w.show()
        sys.exit(app.exec_())