简体   繁体   English

PyQt5 将 QCompleter 添加到现有 QTextEdit

[英]PyQt5 Adding QCompleter to Existing QTextEdit

I am currently creating a SQL Editor and Query Wizard with PyQt5 and am running into an issue when trying to add a QCompleter to all my QPlainTextEdits in the wizard.我目前正在使用 PyQt5 创建 SQL 编辑器和查询向导,并且在尝试将 QCompleter 添加到向导中的所有 QPlainTextEdits 时遇到问题。 All the UI is created with Qt Designer and is stored in a QStackedWidget.所有 UI 都是用 Qt Designer 创建的,并存储在 QStackedWidget 中。

I have read into Promoting the widget in Designer to my custom widget (TextEdit), which is a QTextEdit with the QCompleter model interface.我已经阅读了将 Designer 中的小部件提升到我的自定义小部件 (TextEdit),这是一个带有 QCompleter 模型界面的 QTextEdit。

My question is, how can one set the completer model to an object that is already created?我的问题是,如何将完成模型设置为已经创建的对象? Is there a way to hold off on initializing it until after the completer is set?有没有办法在设置完成者之前推迟初始化它? In another section of the program, I am able to add the widget after its set due to the functionality, but there must be a better way.在程序的另一部分中,由于功能的原因,我可以在设置后添加小部件,但必须有更好的方法。

Any help would be greatly appreciated.任何帮助将不胜感激。 Below is the code that I use to set the way that works.下面是我用来设置工作方式的代码。

tab = QtWidgets.QWidget()
horizontalLayout = QtWidgets.QHBoxLayout(tab)

self.completer = QCompleter(self)


self.all_autocomplete_words.extend(sql_words)
self.all_autocomplete_words = pd.Series(
    self.all_autocomplete_words).sort_values().drop_duplicates().tolist()
#print(self.all_autocomplete_words)
completer_model = QStringListModel(self.all_autocomplete_words, self.completer)

self.completer.setModel(completer_model)
self.completer.setModelSorting(QCompleter.CaseInsensitivelySortedModel)
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
self.completer.setWrapAround(False)
# print(self.auto_completion_words)
# print(self.all_autocomplete_words)
self.completingTextEdit = TextEdit(dict_words=self.auto_completion_words,
                                   list_words=self.all_autocomplete_words, parent=tab)
self.completingTextEdit.setCompleter(self.completer)
self.completingTextEdit.setPlaceholderText('SQL Script')
horizontalLayout.addWidget(self.completingTextEdit)

#sql_ws.setPlaceholderText('SQL Script')
self.sql_tab.addTab(tab, key)

Edit:编辑:

Here is the base class for the minimum example...这是最小示例的基类...

from min_example_fromui import Ui_MainWindow
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QTreeWidget, QTreeWidgetItem, QMenu, QAction, \
    QMessageBox, QTreeWidgetItemIterator, QAbstractItemView, QDialog, QShortcut, QGridLayout, QLabel, QLineEdit,\
    QPushButton, QWhatsThis, QCompleter, QTextEdit, QProgressDialog, QTableWidgetItem, QTableView
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QFile, QStringListModel, Qt, QThread, pyqtSignal, QObject, pyqtSlot, QTimer, QEventLoop
from PyQt5.QtGui import QCursor, QKeySequence, QTextCursor
import pandas as pd

class sqlWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(sqlWindow, self).__init__(parent)
        self.setupUi(self)
        self.sql_words = [
            'ABORT'

        ]
        self.all_autocomplete_words = []
        self.auto_completion_words = {}
        self.pushButton.clicked.connect(self.add_tab)

    def add_tab(self):
        tab = QtWidgets.QWidget()
        horizontalLayout = QtWidgets.QHBoxLayout(tab)


        self.completer = QCompleter(self)


        self.all_autocomplete_words.extend(self.sql_words)
        self.all_autocomplete_words = pd.Series(
            self.all_autocomplete_words).sort_values().drop_duplicates().tolist()
        #print(self.all_autocomplete_words)



        completer_model = QStringListModel(self.all_autocomplete_words, self.completer)

        self.completer.setModel(completer_model)
        self.completer.setModelSorting(QCompleter.CaseInsensitivelySortedModel)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setWrapAround(False)
        # print(self.auto_completion_words)
        # print(self.all_autocomplete_words)
        self.completingTextEdit = TextEdit(dict_words=self.auto_completion_words,
                                           list_words=self.all_autocomplete_words, parent=tab)
        self.completingTextEdit.setCompleter(self.completer)
        self.completingTextEdit.setPlaceholderText('SQL Script')
        horizontalLayout.addWidget(self.completingTextEdit)

        # sql_ws.setPlaceholderText('SQL Script')
        self.sql_tab.addTab(tab, 'key')
        self.sql_tab.setCurrentWidget(tab)

class TextEdit(QTextEdit):
    def __init__(self, dict_words=dict, list_words=list, parent=None):
        super(TextEdit, self).__init__(parent)

        self._completer = None
        self.auto_complete_dict = dict_words
        self.all_autocomplete = list_words
        #Class Instances
        self.completion_prefix = ''


    def setCompleter(self, c):

        self._completer = c
        c.setWidget(self)
        c.setCompletionMode(QCompleter.PopupCompletion)
        c.setCaseSensitivity(Qt.CaseInsensitive)
        c.activated.connect(self.insertCompletion)


    def insertCompletion(self, completion):
        if self._completer.widget() is not self:
            return

        tc = self.textCursor()
        extra = len(completion) - len(self._completer.completionPrefix())
        tc.movePosition(QTextCursor.Left)
        tc.movePosition(QTextCursor.EndOfWord)

        if self.completion_prefix.lower() == completion[-extra:].lower():
            pass
            #print('You inserted the word after it was completed')
        else:
            tc.insertText(completion[-extra:])
            #print('The text being inserted',completion[-extra:])
            self.setTextCursor(tc)
            self._completer.setModel(QStringListModel(self.all_autocomplete, self._completer))

    def textUnderCursor(self):
        tc = self.textCursor()
        tc.select(QTextCursor.WordUnderCursor)
        #print('Here is the selected text under the cursor' , tc.selectedText())
        return tc.selectedText()

    def focusInEvent(self, e):
        #Open the widget where you are at in the edit
        if self._completer is not None:
            self._completer.setWidget(self)
        super(TextEdit, self).focusInEvent(e)

    def keyPressEvent(self, e):

        isShortcut = False

        if self._completer is not None and self._completer.popup().isVisible():
            #print('Popup is up')
            # The following keys are forwarded by the completer to the widget.
            if e.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Backtab):
                e.ignore()
                #self._completer.setModel(QStringListModel(self.all_autocomplete, self._completer))
                # Let the completer do default behavior.
                return

        if e.key() == Qt.Key_E and e.modifiers() == Qt.ControlModifier:
            #Control + E was pressed.
            words = self.all_autocomplete
            self._completer.setModel(QStringListModel(words, self._completer))
            isShortcut = True

        if e.key() == Qt.Key_Period:
            #This is how I will do the lookup functionality. Show when period is his, open the list of options.
            self.textCursor().insertText('.')
            self.moveCursor(QtGui.QTextCursor.PreviousWord)
            self.moveCursor(QtGui.QTextCursor.PreviousWord, QtGui.QTextCursor.KeepAnchor)
            dict_key = self.textCursor().selectedText().upper()
            #print('Dict Key' , dict_key)
            self.moveCursor(QtGui.QTextCursor.NextWord)
            self.moveCursor(QtGui.QTextCursor.NextWord)

            #print(dict_key)
            words = self.auto_complete_dict[dict_key]
            self._completer.setModel(QStringListModel(words, self._completer))
            isShortcut = True

        if self._completer is None or not isShortcut:
            # Do not process the shortcut when we have a completer.
            super(TextEdit, self).keyPressEvent(e)

        ctrlOrShift = e.modifiers() & (Qt.ControlModifier | Qt.ShiftModifier)
        if self._completer is None or (ctrlOrShift and len(e.text()) == 0):
            return

        eow = "~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="
        hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift


        completionPrefix = self.textUnderCursor()
        self.completion_prefix = completionPrefix
        #print('CompletionPrefix :' , completionPrefix)

        if not isShortcut and (hasModifier or len(e.text()) == 0 or len(completionPrefix) < 2 or e.text()[-1] in eow):
            self._completer.popup().hide()
            return

        if completionPrefix != self._completer.completionPrefix():
            #Puts the Prefix of the word youre typing into the Prefix
            self._completer.setCompletionPrefix(completionPrefix)
            self._completer.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)

if __name__ == "__main__":
    import sys

    '''These excepthook lines are to catch errors when using pyqt5'''
    sys._excepthook = sys.excepthook
    def exception_hook(exctype, value, traceback):
        print(exctype, value, traceback)
        sys._excepthook(exctype, value, traceback)
        sys.exit(1)
    sys.excepthook = exception_hook
    '''Error handling section to raise errors'''

    app = QApplication(sys.argv)
    main_window = sqlWindow()
    main_window.show()
    sys.exit(app.exec_())

And here is my ui code:这是我的用户界面代码:

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.sql_tab = QtWidgets.QTabWidget(self.centralwidget)
        self.sql_tab.setEnabled(True)
        self.sql_tab.setTabsClosable(True)
        self.sql_tab.setMovable(True)
        self.sql_tab.setObjectName("sql_tab")
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName("tab")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.tab)
        self.gridLayout_2.setObjectName("gridLayout_2")
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout_2.addItem(spacerItem, 0, 2, 1, 1)
        spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout_2.addItem(spacerItem1, 0, 0, 1, 1)
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.label_2 = QtWidgets.QLabel(self.tab)
        self.label_2.setObjectName("label_2")
        self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1)
        self.pushButton = QtWidgets.QPushButton(self.tab)
        self.pushButton.setObjectName("pushButton")
        self.gridLayout.addWidget(self.pushButton, 0, 1, 1, 1)
        self.gridLayout_2.addLayout(self.gridLayout, 1, 1, 1, 1)
        self.label = QtWidgets.QLabel(self.tab)
        self.label.setFrameShape(QtWidgets.QFrame.Box)
        self.label.setLineWidth(0)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.label.setObjectName("label")
        self.gridLayout_2.addWidget(self.label, 0, 1, 1, 1)
        self.sql_tab.addTab(self.tab, "")
        self.verticalLayout.addWidget(self.sql_tab)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.sql_tab.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label_2.setText(_translate("MainWindow", "For Help, refer to the User Manual."))
        self.pushButton.setText(_translate("MainWindow", "User Manual"))
        self.label.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-size:18pt;\">SQL Editor Welcome Sheet</span></p><p><br/></p><p>Only List Reports Can be Ran by Worksheet. </p><p>All Other Reports are Ran Through the Query Builder.</p></body></html>"))
        self.sql_tab.setTabText(self.sql_tab.indexOf(self.tab), _translate("MainWindow", "SQL Editor Home"))

Thanks!谢谢!

Second Edit:第二次编辑:

from min_example_fromui import Ui_MainWindow
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QTreeWidget, QTreeWidgetItem, QMenu, QAction, \
    QMessageBox, QTreeWidgetItemIterator, QAbstractItemView, QDialog, QShortcut, QGridLayout, QLabel, QLineEdit,\
    QPushButton, QWhatsThis, QCompleter, QTextEdit, QProgressDialog, QTableWidgetItem, QTableView
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QFile, QStringListModel, Qt, QThread, pyqtSignal, QObject, pyqtSlot, QTimer, QEventLoop
from PyQt5.QtGui import QCursor, QKeySequence, QTextCursor
import pandas as pd

    class sqlWindow(QMainWindow, Ui_MainWindow):
        def __init__(self, parent=None):
            super(sqlWindow, self).__init__(parent)
            self.setupUi(self)
            self.sql_words = [
                'ABORT'

            ]
            self.all_autocomplete_words = []
            self.auto_completion_words = {}
            self.pushButton.clicked.connect(self.add_tab)

            self.completer = QCompleter(self)

            self.all_autocomplete_words.extend(self.sql_words)
            self.all_autocomplete_words = pd.Series(
                self.all_autocomplete_words).sort_values().drop_duplicates().tolist()
            # print(self.all_autocomplete_words)

            self.completer_model = QStringListModel(self.all_autocomplete_words, self.completer)
            self.completer.setModel(self.completer_model)
            self.completer.setModelSorting(QCompleter.CaseInsensitivelySortedModel)
            self.completer.setCaseSensitivity(Qt.CaseInsensitive)
            self.completer.setWrapAround(False)

            self.my_sqlbox = TextEdit(dict_words=self.auto_completion_words,
                                               list_words=self.all_autocomplete_words, parent=None)
            self.my_sqlbox.setCompleter(self.completer)
            self.my_sqlbox.setPlaceholderText('SQL Script')

        def add_tab(self):
            tab = QtWidgets.QWidget()
            horizontalLayout = QtWidgets.QHBoxLayout(tab)


            self.completingTextEdit = TextEdit(dict_words=self.auto_completion_words,
                                               list_words=self.all_autocomplete_words, parent=tab)
            self.completingTextEdit.setCompleter(self.completer)
            self.completingTextEdit.setPlaceholderText('SQL Script')
            horizontalLayout.addWidget(self.completingTextEdit)

            # sql_ws.setPlaceholderText('SQL Script')
            self.sql_tab.addTab(tab, 'key')
            self.sql_tab.setCurrentWidget(tab)

    class TextEdit(QTextEdit):
        def __init__(self, dict_words=dict, list_words=list, parent=None):
            super(TextEdit, self).__init__(parent)

            self._completer = None
            self.auto_complete_dict = dict_words
            self.all_autocomplete = list_words
            #Class Instances
            self.completion_prefix = ''


        def setCompleter(self, c):

            self._completer = c
            c.setWidget(self)
            c.setCompletionMode(QCompleter.PopupCompletion)
            c.setCaseSensitivity(Qt.CaseInsensitive)
            c.activated.connect(self.insertCompletion)


        def insertCompletion(self, completion):
            if self._completer.widget() is not self:
                return

            tc = self.textCursor()
            extra = len(completion) - len(self._completer.completionPrefix())
            tc.movePosition(QTextCursor.Left)
            tc.movePosition(QTextCursor.EndOfWord)

            if self.completion_prefix.lower() == completion[-extra:].lower():
                pass
                #print('You inserted the word after it was completed')
            else:
                tc.insertText(completion[-extra:])
                #print('The text being inserted',completion[-extra:])
                self.setTextCursor(tc)
                self._completer.setModel(QStringListModel(self.all_autocomplete, self._completer))

        def textUnderCursor(self):
            tc = self.textCursor()
            tc.select(QTextCursor.WordUnderCursor)
            #print('Here is the selected text under the cursor' , tc.selectedText())
            return tc.selectedText()

        def focusInEvent(self, e):
            #Open the widget where you are at in the edit
            if self._completer is not None:
                self._completer.setWidget(self)
            super(TextEdit, self).focusInEvent(e)

        def keyPressEvent(self, e):

            isShortcut = False

            if self._completer is not None and self._completer.popup().isVisible():
                #print('Popup is up')
                # The following keys are forwarded by the completer to the widget.
                if e.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Backtab):
                    e.ignore()
                    #self._completer.setModel(QStringListModel(self.all_autocomplete, self._completer))
                    # Let the completer do default behavior.
                    return

            if e.key() == Qt.Key_E and e.modifiers() == Qt.ControlModifier:
                #Control + E was pressed.
                words = self.all_autocomplete
                self._completer.setModel(QStringListModel(words, self._completer))
                isShortcut = True

            if e.key() == Qt.Key_Period:
                #This is how I will do the lookup functionality. Show when period is his, open the list of options.
                self.textCursor().insertText('.')
                self.moveCursor(QtGui.QTextCursor.PreviousWord)
                self.moveCursor(QtGui.QTextCursor.PreviousWord, QtGui.QTextCursor.KeepAnchor)
                dict_key = self.textCursor().selectedText().upper()
                #print('Dict Key' , dict_key)
                self.moveCursor(QtGui.QTextCursor.NextWord)
                self.moveCursor(QtGui.QTextCursor.NextWord)

                #print(dict_key)
                words = self.auto_complete_dict[dict_key]
                self._completer.setModel(QStringListModel(words, self._completer))
                isShortcut = True

            if self._completer is None or not isShortcut:
                # Do not process the shortcut when we have a completer.
                super(TextEdit, self).keyPressEvent(e)

            ctrlOrShift = e.modifiers() & (Qt.ControlModifier | Qt.ShiftModifier)
            if self._completer is None or (ctrlOrShift and len(e.text()) == 0):
                return

            eow = "~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="
            hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift


            completionPrefix = self.textUnderCursor()
            self.completion_prefix = completionPrefix
            #print('CompletionPrefix :' , completionPrefix)

            if not isShortcut and (hasModifier or len(e.text()) == 0 or len(completionPrefix) < 2 or e.text()[-1] in eow):
                self._completer.popup().hide()
                return

            if completionPrefix != self._completer.completionPrefix():
                #Puts the Prefix of the word youre typing into the Prefix
                self._completer.setCompletionPrefix(completionPrefix)
                self._completer.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)

    if __name__ == "__main__":
        import sys

        '''These excepthook lines are to catch errors when using pyqt5'''
        sys._excepthook = sys.excepthook
        def exception_hook(exctype, value, traceback):
            print(exctype, value, traceback)
            sys._excepthook(exctype, value, traceback)
            sys.exit(1)
        sys.excepthook = exception_hook
        '''Error handling section to raise errors'''

        app = QApplication(sys.argv)
        main_window = sqlWindow()
        main_window.show()
        sys.exit(app.exec_())

Static QPlainText from ui来自 ui 的静态 QPlainText

So for those in the future who run into this problem, I attempted to promote the widget in Qt Designer.所以对于以后遇到这个问题的人,我尝试在 Qt Designer 中推广这个小部件。 However, I ran into issues when trying to add the arguments for the QCompleter.但是,我在尝试为 QCompleter 添加参数时遇到了问题。 What I had to end up doing was to remove the QPlainTextEdit upon load and then call a function to add the new TextEdit class that I created along with the QCompleter.我最终要做的是在加载时删除 QPlainTextEdit,然后调用一个函数来添加我与 QCompleter 一起创建的新 TextEdit 类。

See code below:见下面的代码:

from min_example_fromui import Ui_MainWindow
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QTreeWidget, QTreeWidgetItem, QMenu, QAction, \
    QMessageBox, QTreeWidgetItemIterator, QAbstractItemView, QDialog, QShortcut, QGridLayout, QLabel, QLineEdit,\
    QPushButton, QWhatsThis, QCompleter, QTextEdit, QProgressDialog, QTableWidgetItem, QTableView
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QFile, QStringListModel, Qt, QThread, pyqtSignal, QObject, pyqtSlot, QTimer, QEventLoop
from PyQt5.QtGui import QCursor, QKeySequence, QTextCursor
import pandas as pd

class sqlWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(sqlWindow, self).__init__(parent)
        self.setupUi(self)
        self.sql_words = [
            'ABORT'
        ]
        self.all_autocomplete_words = []
        self.auto_completion_words = {}

        ##################Delete the existing QPlainTextEdit############
        self.my_sqlbox.deleteLater()


        self.pushButton.clicked.connect(self.add_tab)
        self.pushButton_2.clicked.connect(self.test)
        self.completer = QCompleter(self)

        self.all_autocomplete_words.extend(self.sql_words)
        self.all_autocomplete_words = pd.Series(
            self.all_autocomplete_words).sort_values().drop_duplicates().tolist()
        # print(self.all_autocomplete_words)

        self.completer_model = QStringListModel(self.all_autocomplete_words, self.completer)
        self.completer.setModel(self.completer_model)
        self.completer.setModelSorting(QCompleter.CaseInsensitivelySortedModel)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setWrapAround(False)

        #######RIGHT HERE IS WHERE I CALL THE NEW TextEdit creation#######
        self.makeText()





    def add_tab(self):
        tab = QtWidgets.QWidget()
        horizontalLayout = QtWidgets.QHBoxLayout(tab)


        self.completingTextEdit = TextEdit(dict_words=self.auto_completion_words,
                                           list_words=self.all_autocomplete_words, parent=tab)
        self.completingTextEdit.setCompleter(self.completer)
        self.completingTextEdit.setPlaceholderText('SQL Script')
        horizontalLayout.addWidget(self.completingTextEdit)

        # sql_ws.setPlaceholderText('SQL Script')
        self.sql_tab.addTab(tab, 'key')
        self.sql_tab.setCurrentWidget(tab)

    def makeText(self):
        self.my_sqlbox = TextEdit(dict_words=self.auto_completion_words,
                                  list_words=self.all_autocomplete_words, parent=None)
        self.my_sqlbox.setCompleter(self.completer)
        self.my_sqlbox.setPlaceholderText('SQL Script')
        self.gridLayout_2.addWidget(self.my_sqlbox ,0, 1, 1, 1)

class TextEdit(QTextEdit):
    def __init__(self, dict_words=dict, list_words=list, parent=None):
        super(TextEdit, self).__init__(parent)

        self._completer = None
        self.auto_complete_dict = dict_words
        self.all_autocomplete = list_words
        #Class Instances
        self.completion_prefix = ''


    def setCompleter(self, c):

        self._completer = c
        c.setWidget(self)
        c.setCompletionMode(QCompleter.PopupCompletion)
        c.setCaseSensitivity(Qt.CaseInsensitive)
        c.activated.connect(self.insertCompletion)


    def insertCompletion(self, completion):
        if self._completer.widget() is not self:
            return

        tc = self.textCursor()
        extra = len(completion) - len(self._completer.completionPrefix())
        tc.movePosition(QTextCursor.Left)
        tc.movePosition(QTextCursor.EndOfWord)

        if self.completion_prefix.lower() == completion[-extra:].lower():
            pass
            #print('You inserted the word after it was completed')
        else:
            tc.insertText(completion[-extra:])
            #print('The text being inserted',completion[-extra:])
            self.setTextCursor(tc)
            self._completer.setModel(QStringListModel(self.all_autocomplete, self._completer))

    def textUnderCursor(self):
        tc = self.textCursor()
        tc.select(QTextCursor.WordUnderCursor)
        #print('Here is the selected text under the cursor' , tc.selectedText())
        return tc.selectedText()

    def focusInEvent(self, e):
        #Open the widget where you are at in the edit
        if self._completer is not None:
            self._completer.setWidget(self)
        super(TextEdit, self).focusInEvent(e)

    def keyPressEvent(self, e):

        isShortcut = False

        if self._completer is not None and self._completer.popup().isVisible():
            #print('Popup is up')
            # The following keys are forwarded by the completer to the widget.
            if e.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Backtab):
                e.ignore()
                #self._completer.setModel(QStringListModel(self.all_autocomplete, self._completer))
                # Let the completer do default behavior.
                return

        if e.key() == Qt.Key_E and e.modifiers() == Qt.ControlModifier:
            #Control + E was pressed.
            words = self.all_autocomplete
            self._completer.setModel(QStringListModel(words, self._completer))
            isShortcut = True

        if e.key() == Qt.Key_Period:
            #This is how I will do the lookup functionality. Show when period is his, open the list of options.
            self.textCursor().insertText('.')
            self.moveCursor(QtGui.QTextCursor.PreviousWord)
            self.moveCursor(QtGui.QTextCursor.PreviousWord, QtGui.QTextCursor.KeepAnchor)
            dict_key = self.textCursor().selectedText().upper()
            #print('Dict Key' , dict_key)
            self.moveCursor(QtGui.QTextCursor.NextWord)
            self.moveCursor(QtGui.QTextCursor.NextWord)

            #print(dict_key)
            words = self.auto_complete_dict[dict_key]
            self._completer.setModel(QStringListModel(words, self._completer))
            isShortcut = True

        if self._completer is None or not isShortcut:
            # Do not process the shortcut when we have a completer.
            super(TextEdit, self).keyPressEvent(e)

        ctrlOrShift = e.modifiers() & (Qt.ControlModifier | Qt.ShiftModifier)
        if self._completer is None or (ctrlOrShift and len(e.text()) == 0):
            return

        eow = "~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="
        hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift


        completionPrefix = self.textUnderCursor()
        self.completion_prefix = completionPrefix
        #print('CompletionPrefix :' , completionPrefix)

        if not isShortcut and (hasModifier or len(e.text()) == 0 or len(completionPrefix) < 2 or e.text()[-1] in eow):
            self._completer.popup().hide()
            return

        if completionPrefix != self._completer.completionPrefix():
            #Puts the Prefix of the word youre typing into the Prefix
            self._completer.setCompletionPrefix(completionPrefix)
            self._completer.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)

if __name__ == "__main__":
    import sys

    '''These excepthook lines are to catch errors when using pyqt5'''
    sys._excepthook = sys.excepthook
    def exception_hook(exctype, value, traceback):
        print(exctype, value, traceback)
        sys._excepthook(exctype, value, traceback)
        sys.exit(1)
    sys.excepthook = exception_hook
    '''Error handling section to raise errors'''

    app = QApplication(sys.argv)
    main_window = sqlWindow()
    main_window.show()
    sys.exit(app.exec_())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM