PyQt5中QCompleter仅能补全整句无法逐词补全的问题如何解决
PyQt5 QCompleter 实现多单词逐词补全方案
核心实现思路:QCompleter默认对输入框全量文本做匹配,我们只需修改逻辑,仅提取当前光标位置正在输入的单个单词做补全匹配,补全后替换对应位置的单词即可,不影响已输入的其他内容。
修改后完整可运行代码
import sys from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTextEdit, QLineEdit, QCompleter from PyQt5.QtGui import QStandardItem, QStandardItemModel, QFont from PyQt5.QtCore import Qt class WordCompleter(QCompleter): def __init__(self, parent=None): super().__init__(parent) self.setFilterMode(Qt.MatchStartsWith) self.setCaseSensitivity(Qt.CaseInsensitive) class AppDemo(QWidget): def __init__(self): super().__init__() self.resize(1200, 800) self.word_separator = ' ' fnt = QFont('Open Sans', 12) mainLayout = QVBoxLayout() # 输入框 self.input = QLineEdit() self.input.setFixedHeight(50) self.input.setFont(fnt) self.input.textEdited.connect(self.addEntry) mainLayout.addWidget(self.input) # 补全组件配置 self.model = QStandardItemModel() self.completer = WordCompleter(self.model, self) self.input.setCompleter(self.completer) # 绑定补全选中事件 self.completer.activated.connect(self.on_completed) # 回显区域 self.console = QTextEdit() self.console.setFont(fnt) mainLayout.addWidget(self.console) self.setLayout(mainLayout) def get_current_word(self): # 获取当前光标前的输入内容,拆分得到正在输入的单词 cursor_pos = self.input.cursorPosition() text = self.input.text()[:cursor_pos] return text.split(self.word_separator)[-1] def on_completed(self, text): # 补全选中后替换当前单词,而非替换整个输入框内容 cursor_pos = self.input.cursorPosition() full_text = self.input.text() before_text = full_text[:cursor_pos] # 计算当前单词的起始位置 start_pos = before_text.rfind(self.word_separator) + 1 # 拼接新的文本 new_text = full_text[:start_pos] + text + full_text[cursor_pos:] self.input.setText(new_text) # 光标移到补全的单词后面 self.input.setCursorPosition(start_pos + len(text)) def addEntry(self): entryItem = self.input.text() self.console.clear() self.console.append(entryItem) # 按空格拆分所有单词,逐个加入补全候选池 words = entryItem.split(self.word_separator) for word in words: word = word.strip() if word and not self.model.findItems(word): self.model.appendRow(QStandardItem(word)) # 实时更新补全前缀为当前正在输入的单词 current_word = self.get_current_word() if current_word: self.completer.setCompletionPrefix(current_word) if self.completer.completionCount() > 0: self.completer.complete() if __name__ == '__main__': app = QApplication(sys.argv) demo = AppDemo() demo.show() sys.exit(app.exec_())
关键改动说明
- 自定义
WordCompleter类,默认配置前缀匹配、不区分大小写,适配单词补全场景 - 新增
get_current_word方法,根据光标位置拆分输入文本,仅提取当前正在输入的单词作为补全匹配前缀 - 重写补全选中逻辑
on_completed,选中补全项后仅替换当前位置的单词,保留之前输入的所有内容 - 修改候选词入库逻辑,将输入内容按空格拆分后逐个加入候选池,而非添加整个输入短语
- 每次输入内容变更时主动更新补全前缀,触发补全提示弹出
内容的提问来源于stack exchange,提问作者lucas
相关产品推荐
相关产品推荐

