PyQt5 QTextEdit自动补全

PyQt5 QTextEdit auto completion

正在寻找一种使用 QTextEdit 和 QCompleter 进行自动完成的方法。我读过这是可能的,但没有找到任何例子...... 我正在使用 python3.4 和 PyQt5

我正在寻找一个非常基本的示例 感谢您的帮助

这里有一个例子……我已经研究过了……尽管它在 python3.3 和 pyqt4 中。我想它应该不会有太大的不同..
你将不得不改变从PyQt4从PyQt5

快捷键是 Ctrl+Space 显示建议和 Ctrl+ E 自动完成第一个可行的建议

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-------------------------------|

编辑

附上截图。

如果有人感兴趣,这里是一个“不完整”的解决方案。 这是我所做的。 我已更改为 PlainTextEdit,因为没有显着优势 使用 QTextEdit

编辑

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()

完成者

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