如何使用PyQt5 QCompleter完成代码

时间:2018-04-19 21:31:00

标签: python pyqt pyqt5 tab-completion qcompleter

我想创建一个具有基本代码完成功能的QLineEdit字段,但到目前为止,每当我选择项item.attr的属性时,item.都会被{{1}替换而不是在attr之后插入attr。此外,如果item.attr,则无法预测,因为attr.subattr已被替换且item.在我的模型的根目录中不存在。

我创建了一个相对最小的例子:

attr.

我从Qt5 Docsexample with Qt4.6中提出了这种方法,但两者都没有结合我想要完成的所有内容。我需要不同的模型结构吗?我是否需要继承import sys from PyQt5.QtGui import QStandardItemModel, QStandardItem from PyQt5.QtWidgets import QApplication,QWidget,QVBoxLayout,QLineEdit,QCompleter test_model_data = [ ('tree',[ # tree ('branch', [ # tree.branch ('leaf',[])]), # tree.branch.leaf ('roots', [])]), # tree.roots ('house',[ # house ('kitchen',[]), # house.kitchen ('bedroom',[])]), # house.bedroom ('obj3',[]), # etc.. ('obj4',[]) ] class codeCompleter(QCompleter): def splitPath(self, path): return path.split('.') #split table.member class mainApp(QWidget): def __init__(self): super().__init__() self.entry = QLineEdit(self) self.model = QStandardItemModel(parent=self) self.completer = codeCompleter(self.model, self) self.entry.setCompleter(self.completer) layout = QVBoxLayout() layout.addWidget(self.entry) self.setLayout(layout) self.update_model() #normally called from a signal when new data is available def update_model(self): def addItems(parent, elements): for text, children in elements: item = QStandardItem(text) parent.appendRow(item) if children: addItems(item, children) addItems(self.model, test_model_data) if __name__ == "__main__": app = QApplication(sys.argv) hwind = mainApp() hwind.show() sys.exit(app.exec_())的更多内容?我需要一个不同的QCompleter课程吗?

示例的GIF :(抱歉质量)

enter image description here

尾声:

对于那些对实际代码完成感兴趣的人,我在整合@ eyllanesc的答案后扩展了我的代码,以便匹配的标识符序列之前的文本保持不变(匹配序列之前的文本不会阻止匹配,也不会插入新匹配时删除)。所有这一切都需要一点正则表达式来将我们想要完成的部分与前面的文本分开:

Qt

1 个答案:

答案 0 :(得分:3)

pathFromIndex()方法返回将放置在QLineEdit中的字符串,而不是它将返回项目文本和其前任文本的串联。为了提高效率并且不计算在线连接,将为包含该数据的模型创建一个新角色。

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLineEdit, QCompleter

test_model_data = [
    ('tree',[                           # tree
             ('branch', [               # tree.branch
                         ('leaf',[])]), # tree.branch.leaf
             ('roots',  [])]),          # tree.roots
    ('house',[                          # house
                ('kitchen',[]),         # house.kitchen
                ('bedroom',[])]),       # house.bedroom
    ('obj3',[]),                        # etc..
    ('obj4',[])
]


class CodeCompleter(QCompleter):
    ConcatenationRole = Qt.UserRole + 1
    def __init__(self, data, parent=None):
        super().__init__(parent)
        self.create_model(data)

    def splitPath(self, path):
        return path.split('.')

    def pathFromIndex(self, ix):
        return ix.data(CodeCompleter.ConcatenationRole)

    def create_model(self, data):
        def addItems(parent, elements, t=""):
            for text, children in elements:
                item = QStandardItem(text)
                data = t + "." + text if t else text
                item.setData(data, CodeCompleter.ConcatenationRole)
                parent.appendRow(item)
                if children:
                    addItems(item, children, data)
        model = QStandardItemModel(self)
        addItems(model, data)
        self.setModel(model)

class mainApp(QWidget):
    def __init__(self):
        super().__init__()
        self.entry = QLineEdit(self)
        self.completer = CodeCompleter(test_model_data, self)
        self.entry.setCompleter(self.completer)
        layout = QVBoxLayout()
        layout.addWidget(self.entry)
        self.setLayout(layout)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    hwind = mainApp()
    hwind.show()
    sys.exit(app.exec_())