PyQt5 QTextEdit finalización automática

Buscando una manera de tener una finalización automática con un QTextEdit y QCompleter. He leído que es posible pero no encontré ningún ejemplo … Estoy usando python3.4 y PyQt5

Estoy buscando un ejemplo muy básico, gracias por cualquier ayuda.

Un ejemplo aquí … en el que he trabajado … aunque está en python3.3 y pyqt4. Supongo que no debería hacer mucha diferencia …
tendrá que cambiar de PyQt4 a de PyQt5

las teclas de método abreviado son Ctrl + Espacio para mostrar sugerencias y Ctrl + E para autocompletar la primera sugerencia disponible

mMyTextEdit.py

from PyQt4 import QtGui,QtCore from mMyDictionaryCompleter import MyDictionaryCompleter #=============================================================================== # MyTextEdit #=============================================================================== class MyTextEdit(QtGui.QTextEdit): #|-----------------------------------------------------------------------------| # class Variables #|-----------------------------------------------------------------------------| #no classVariables # myFocusOutSignal=QtCore.pyqtSignal(str) #|-----------------------------------------------------------------------------| # Constructor #|-----------------------------------------------------------------------------| def __init__(self,*args): #*args to set parent QtGui.QLineEdit.__init__(self,*args) font=QtGui.QFont() font.setPointSize(12) self.setFont(font) self.completer = None #|--------------------------End of __init__------------------------------------| #|-----------------------------------------------------------------------------| # setCompleter #|-----------------------------------------------------------------------------| def setCompleter(self, completer): if self.completer: self.disconnect(self.completer, 0, self, 0) if not completer: return completer.setWidget(self) completer.setCompletionMode(QtGui.QCompleter.PopupCompletion) completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.completer = completer # self.connect(self.completer, # QtCore.SIGNAL("activated(const QString&)"), self.insertCompletion) self.completer.insertText.connect(self.insertCompletion) #|-----------------------End of setCompleter-------------------------------------| #|-----------------------------------------------------------------------------| # insertCompletion #|-----------------------------------------------------------------------------| def insertCompletion(self, completion): tc = self.textCursor() extra = (len(completion) - len(self.completer.completionPrefix())) tc.movePosition(QtGui.QTextCursor.Left) tc.movePosition(QtGui.QTextCursor.EndOfWord) tc.insertText(completion[-extra:]) self.setTextCursor(tc) #|-----------------------End of insertCompletion-------------------------------| #|-----------------------------------------------------------------------------| # textUnderCursor #|-----------------------------------------------------------------------------| def textUnderCursor(self): tc = self.textCursor() tc.select(QtGui.QTextCursor.WordUnderCursor) return tc.selectedText() #|-----------------------End of textUnderCursor--------------------------------| #|-----------------------------------------------------------------------------| # focusInEvent #|-----------------------------------------------------------------------------| #---override def focusInEvent(self, event): if self.completer: self.completer.setWidget(self); QtGui.QTextEdit.focusInEvent(self, event) #|-----------------------End of focusInEvent-------------------------------------| #|-----------------------------------------------------------------------------| # keyPressEvent #|-----------------------------------------------------------------------------| #---override def keyPressEvent(self, event): if self.completer and self.completer.popup() and self.completer.popup().isVisible(): if event.key() in ( QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return, QtCore.Qt.Key_Escape, QtCore.Qt.Key_Tab, QtCore.Qt.Key_Backtab): event.ignore() return ## has ctrl-Space been pressed?? isShortcut = (event.modifiers() == QtCore.Qt.ControlModifier and\ event.key() == QtCore.Qt.Key_Space) ## modifier to complete suggestion inline ctrl-e inline = (event.modifiers() == QtCore.Qt.ControlModifier and \ event.key() == QtCore.Qt.Key_E) ## if inline completion has been chosen if inline: # set completion mode as inline self.completer.setCompletionMode(QtGui.QCompleter.InlineCompletion) completionPrefix = self.textUnderCursor() if (completionPrefix != self.completer.completionPrefix()): self.completer.setCompletionPrefix(completionPrefix) self.completer.complete() # self.completer.setCurrentRow(0) # self.completer.activated.emit(self.completer.currentCompletion()) # set the current suggestion in the text box self.completer.insertText.emit(self.completer.currentCompletion()) # reset the completion mode self.completer.setCompletionMode(QtGui.QCompleter.PopupCompletion) return if (not self.completer or not isShortcut): pass QtGui.QTextEdit.keyPressEvent(self, event) # debug # print("After controlspace") # print("isShortcut is: {}".format(isShortcut)) # debug over ## ctrl or shift key on it's own?? ctrlOrShift = event.modifiers() in (QtCore.Qt.ControlModifier ,\ QtCore.Qt.ShiftModifier) if ctrlOrShift and event.text()== '': # ctrl or shift key on it's own return # debug # print("After on its own") # print("isShortcut is: {}".format(isShortcut)) # debug over # eow = QtCore.QString("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-=") #end of word # eow = "~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-=" #end of word eow = "~!@#$%^&*+{}|:\"<>?,./;'[]\\-=" #end of word hasModifier = ((event.modifiers() != QtCore.Qt.NoModifier) and\ not ctrlOrShift) completionPrefix = self.textUnderCursor() # print('event . text = {}'.format(event.text().right(1))) # if (not isShortcut and (hasModifier or event.text()=='' or\ # len(completionPrefix) < 3 or \ # eow.contains(event.text().right(1)))): if not isShortcut : if self.completer.popup(): self.completer.popup().hide() return # print("complPref: {}".format(completionPrefix)) # print("completer.complPref: {}".format(self.completer.completionPrefix())) # print("mode: {}".format(self.completer.completionMode())) # if (completionPrefix != self.completer.completionPrefix()): self.completer.setCompletionPrefix(completionPrefix) popup = self.completer.popup() popup.setCurrentIndex( self.completer.completionModel().index(0,0)) cr = self.cursorRect() cr.setWidth(self.completer.popup().sizeHintForColumn(0) + self.completer.popup().verticalScrollBar().sizeHint().width()) self.completer.complete(cr) ## popup it up! #|-----------------------End of keyPressEvent----------------------------------| if __name__ == "__main__": app = QtGui.QApplication([]) completer = MyDictionaryCompleter() te = MyTextEdit() te.setCompleter(completer) te.show() app.exec_() 

mMyDictionaryCompleter.py

 #=============================================================================== # MyDictionaryCompleter #=============================================================================== from PyQt4 import QtGui, QtCore class MyDictionaryCompleter(QtGui.QCompleter): #|-----------------------------------------------------------------------------| # class Variables #|-----------------------------------------------------------------------------| insertText = QtCore.pyqtSignal(str) #no classVariables #|-----------------------------------------------------------------------------| # Constructor #|-----------------------------------------------------------------------------| def __init__(self, myKeywords=None,parent=None): myKeywords =['apple','aggresive','ball','bat','cat','cycle','dog','dumb',\ 'elephant','engineer','food','file','good','great',\ 'hippopotamus','hyper','india','ireland','just','just',\ 'key','kid','lemon','lead','mute','magic',\ 'news','newyork','orange','oval','parrot','patriot',\ 'question','queue','right','rest','smile','simple',\ 'tree','urban','very','wood','xylophone','yellow',\ 'zebra'] QtGui.QCompleter.__init__(self, myKeywords, parent) self.connect(self, QtCore.SIGNAL("activated(const QString&)"), self.changeCompletion) #|--------------------------End of Constructor---------------------------------| #|-----------------------------------------------------------------------------| # changeCompletion #|-----------------------------------------------------------------------------| def changeCompletion(self, completion): if completion.find("(") != -1: completion = completion[:completion.find("(")] print(completion) self.insertText.emit(completion) #|-----------------------End of changeCompletion-------------------------------| 

EDITAR

Capturas de pantalla adjuntas.
PersonajeSegunda sugerencia seleccionada2da Sugerencia Completada

Si alguien interesado aquí es una solución “incompleta”. Aquí esta lo que hice. He cambiado a PlainTextEdit porque no hubo ventajas significativas para usar QTextEdit

Editor

 from PyQt5.QtWidgets import QCompleter, QPlainTextEdit from PyQt5.QtCore import Qt from PyQt5.QtGui import QTextCursor import MyCompleter class AwesomeTextEdit(QPlainTextEdit): def __init__(self, parent=None): super(AwesomeTextEdit, self).__init__(parent) self.completer = MyCompleterparent() self.completer.setWidget(self) self.completer.insertText.connect(self.insertCompletion) def insertCompletion(self, completion): tc = self.textCursor() extra = (len(completion) - len(self.completer.completionPrefix())) tc.movePosition(QTextCursor.Left) tc.movePosition(QTextCursor.EndOfWord) tc.insertText(completion[-extra:]) self.setTextCursor(tc) self.completer.popup().hide() def focusInEvent(self, event): if self.completer: self.completer.setWidget(self) QPlainTextEdit.focusInEvent(self, event) def keyPressEvent(self, event): tc = self.textCursor() if event.key() == Qt.Key_Tab and self.completer.popup().isVisible(): self.completer.insertText.emit(self.completer.getSelected()) self.completer.setCompletionMode(QCompleter.PopupCompletion) return QPlainTextEdit.keyPressEvent(self, event) tc.select(QTextCursor.WordUnderCursor) cr = self.cursorRect() if len(tc.selectedText()) > 0: self.completer.setCompletionPrefix(tc.selectedText()) popup = self.completer.popup() popup.setCurrentIndex(self.completer.completionModel().index(0,0)) cr.setWidth(self.completer.popup().sizeHintForColumn(0) + self.completer.popup().verticalScrollBar().sizeHint().width()) self.completer.complete(cr) else: self.completer.popup().hide() 

Completar

 from PyQt5.QtWidgets import QCompleter from PyQt5 import QtCore class MyCompleter(QCompleter): insertText = QtCore.pyqtSignal(str) def __init__(self, parent=None): QCompleter.__init__(self, ["test","foo","bar"], parent) self.setCompletionMode(QCompleter.PopupCompletion) self.highlighted.connect(self.setHighlighted) def setHighlighted(self, text): self.lastSelected = text def getSelected(self): return self.lastSelected