我想创建一个QLineEdit
具有基本代码完成功能的字段,但到目前为止,每当我选择一个 item 的属性时item.attr
,它item.
都会被替换attr
而不是插入attr
after item.
。此外,如果它attr
具有attr.subattr
,则无法预测它,因为它item.
已被替换并且attr.
不存在于我的模型的根部。
我创建了一个相对最小的示例:
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_())
我从Qt5 Docs和 Qt4.6 的示例中提出了这种方法,但都没有结合我想要完成的所有内容。我需要不同的模型结构吗?我需要更多的子类QCompleter
吗?我需要不同的Qt
班级吗?
示例的 gif:(对不起质量)
结语:
对于那些对实际代码完成感兴趣的人,我在集成@eyllanesc 的答案后扩展了我的代码,以便在匹配的标识符序列之前的文本被单独保留(匹配序列之前的文本不会阻止匹配,也不会在新匹配时被删除插入)。只需要一点正则表达式将我们想要完成的部分与前面的文本分开:
class CodeCompleter(QCompleter):
ConcatenationRole = Qt.UserRole + 1
def __init__(self, parent=None, data=[]):
super().__init__(parent)
self.create_model(data)
self.regex = re.compile('((?:[_a-zA-Z]+\w*)(?:\.[_a-zA-Z]+\w*)*\.?)$')
def splitPath(self, path): #breaks lineEdit.text() into list of strings to match to model
match = self.regex.search(path)
return match[0].split('.') if match else ['']
def pathFromIndex(self, ix): #gets model node (QStandardItem) and returns "text" for lineEdit.setText(text)
return self.regex.sub(ix.data(CodeCompleter.ConcatenationRole), self.completionPrefix())