Home > database >  How to achieve autocomplete on a substring of QLineEdit in PyQt6?
How to achieve autocomplete on a substring of QLineEdit in PyQt6?

Time:10-26

I'm very new to QT so please assume I know nothing. I want an auto-complete where it only matches against the text after the last comma.

e.g. if my word bank is ["alpha", "beta", "vector space"], and the user currently has typed "epsilon,dog,space" then it should match against "vector space" since "space" is a substring of "vector space".

I'm using PyQt6 and my current code looks something like this (adapted from a YouTube tutorial):

line_of_text = QLineEdit("")
word_bank = [name for name,value in names_dict.items()]
completer = QCompleter(word_bank)
completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
completer.setFilterMode(Qt.MatchContains)
line_of_text.setCompleter(completer)

So currently, if word_bank is ["alpha", "beta", "vector space"], then if line_of_text had the string "epsilon,dog,space" then it wouldn't match against anything because "epsilon,dog,space" isn't a substring of "alpha" nor "beta" nor "vector space".

How can I alter my code to achieve what I would like to achieve? -- I'm experienced with programming, just not with Qt.

PS: I have tried doing

line_of_text.textChanged[str].connect(my_function) 

where my_function takes only the substring of line_of_text after the last comma and feeds it to completer.setCompletionPrefix and then calls completer.complete(). This simply does not work. I assume the reason is that completer.complete() updates the completion prefix from line_of_text, causing the call to completer.setCompletionPrefix to be overwritten immediately after.

CodePudding user response:

One solution is to use the textChanged signal to set the completion prefix, and bypass the built-in behaviour of the line-edit to allow greater control of when and how the completions happen.

Below is a basic implementation that shows how to do that. By default, it only shows completions when the text after the last comma has more than single character - but that can be easily adjusted:

from PyQt6 import QtCore, QtGui, QtWidgets

class Window(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.edit = QtWidgets.QLineEdit()
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.edit)
        word_bank =  ['alpha', 'beta', 'vector space']
        self.completer = QtWidgets.QCompleter(word_bank)
        self.completer.setCaseSensitivity(
            QtCore.Qt.CaseSensitivity.CaseInsensitive)
        self.completer.setFilterMode(QtCore.Qt.MatchFlag.MatchContains)
        self.completer.setWidget(self.edit)
        self.completer.activated.connect(self.handleCompletion)
        self.edit.textChanged.connect(self.handleTextChanged)
        self._completing = False

    def handleTextChanged(self, text):
        if not self._completing:
            found = False
            prefix = text.rpartition(',')[-1]
            if len(prefix) > 1:
                self.completer.setCompletionPrefix(prefix)
                if self.completer.currentRow() >= 0:
                    found = True
            if found:
                self.completer.complete()
            else:
                self.completer.popup().hide()

    def handleCompletion(self, text):
        if not self._completing:
            self._completing = True
            prefix = self.completer.completionPrefix()
            self.edit.setText(self.edit.text()[:-len(prefix)]   text)
            self._completing = False

if __name__ == '__main__':

    app = QtWidgets.QApplication(['Test'])
    window = Window()
    window.setGeometry(600, 100, 300, 50)
    window.show()
    app.exec()

CodePudding user response:

(Assuming str is the string from the text input) Have you tried separating str using the , character, then iterating over each of the words separated by a comma.

for word in str.split(","):
     
      for check in word_bank:
           etc...

the connected function will be called in your case whenever the string entered changes.

  • Related