2

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!

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
SKCSS
  • 37
  • 4
  • Your explanation is a bit confusing, using the dictionary you propose 1) if in the QLineEdit you write `"Geo"` What should the popup show: should not show anything, show `"Washington"` and `"Bush"` or show `"George Washington"` and `"George Bush"`? and 2) if an item is selected, what should be shown in the QLineEdit: `"Geo" + item` or `"George" + item`? – eyllanesc Mar 03 '19 at 03:37
  • @eyllanesc Sorry about the confusion. When I start typing "G", I want it to show "Washington" and "Bush". When "Washington" is selected, I want "Washington" to show. Thank you for clarification suggestions. I will update the question. – SKCSS Mar 03 '19 at 05:16
  • Okay, I have another query: `{George: Washington, George: Bush}` is not a valid dictionary. Could the entry be `{"George": ["Washington", "Bush"]}`?. Also, are you using PyQt4 or PyQt5? – eyllanesc Mar 03 '19 at 05:21
  • You are right. The value will be a list. I guess PyQt5, but I'm new to PyQt and honestly I'm not sure which to pick. – SKCSS Mar 03 '19 at 05:27
  • okay. Do you know how I can solve this problem using PyQt5 @eyllanesc ? – SKCSS Mar 03 '19 at 05:50

1 Answers1

0

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_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241