PyQt5 QCompleter 如何在选择自动完成文本后清除 QLineEdit

PyQt5 QCompleter how to clear the QLineEdit after auto-completion text was selected

如何在使用 QCompleter 选择自动完成文本后清除文本框 (QLineEdit)? - 什么都不适合我。

下面是我的代码的一个更简单的示例:它是一个简单的 "echo" 控制台应用程序,它从 QLineEdit(输入文本框)获取文本命令并将其写入 QTextBrowser(输出文本框)。一旦用户在输入文本框上按下 ENTER,该文本框的文本应该被添加到输出文本框,输入文本框应该被清除(为下一个命令做好准备)。

当输入不在自动完成选项中的新文本时,一切正常:文本被添加到输出文本框中并从输入文本框中清除。但是,当用户从自动完成选项中选择一个选项(使用 down/up 箭头)然后按 ENTER 时,文本将添加到输出文本框中,但不会从输入文本框中删除。 ..

两种情况都调用我的回调函数(触发函数),它应该清除输入文本框,使用:

self.consoleCommandLineEdit.clear()

但是当回车选择自动完成文本时,输入文本框没有被清除... 文本已正确添加到输出文本框中,因此我的回调函数被正确调用。 看起来完成者在我清除它后正在填充我的文本框...... 如何禁用此行为并确保清除输入文本框?我可以删除它吗??

下面是整个例子。您可以通过键入 'zzz' 或不在自动完成列表中的任何其他文本来尝试,然后按 ENTER,然后尝试键入 'a',然后使用键盘向下移动到 'aaa1'(或自动完成选项上的任何其他),然后按 ENTER。在这种情况下,您会看到输入文本框未被清除。

import sys
from PyQt5.QtGui import QStandardItem, QStandardItemModel
from PyQt5.QtWidgets import (
    QApplication,
    QWidget,
    QMainWindow,
    QVBoxLayout,
    QLineEdit,
    QTextBrowser,
    QCompleter,
)


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.setWindowTitle("console")
        self.setGeometry(10, 50, 500, 800)

        # Create text box for input
        self.consoleCommandLineEdit = QLineEdit()
        self.consoleCommandLineEdit.setFixedHeight(25)
        self.consoleCommandLineEdit.editingFinished.connect(self.gotConsoleCommand)

        self.model = QStandardItemModel()
        self.model.appendRow(QStandardItem('aaa1'))
        self.model.appendRow(QStandardItem('aaa2'))
        self.model.appendRow(QStandardItem('aaa3'))
        completer = QCompleter(self.model, self)
        self.consoleCommandLineEdit.setCompleter(completer)

        # Create text box for output
        self.consoleViewer = QTextBrowser(lineWrapMode=QTextBrowser.NoWrap)

        widget = QWidget()
        self.setCentralWidget(widget)
        vlay = QVBoxLayout(widget)
        vlay.addWidget(self.consoleCommandLineEdit)
        vlay.addWidget(self.consoleViewer)

    def gotConsoleCommand(self):
        cmd = self.consoleCommandLineEdit.text()
        self.consoleCommandLineEdit.clear()
        self.consoleViewer.append(cmd)  # add cmd to output box


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

问题是 QCompleter 的任务是完成 QLineEdit 的文本,这就是它正在做的,我详细解释发生了什么:用户选择 QCompleter 的弹出选项之一,然后按回车键,这会导致弹出窗口关闭,但也会将回车键的事件发送到 QLineEdit,导致发出 editingFinished 信号,您的代码删除了文本,但 QCompleter 随后添加了所选文本。

解决方案是,在添加该文本后,您必须使用 QTimer 和激活的 QCompleter 信号进行清理:

    # ...
    completer = QCompleter(self.model, self)
    <b>completer.activated.connect(self.onActivated)</b>
    # ...

<b>def onActivated(self):
    QTimer.singleShot(0, self.consoleCommandLineEdit.clear)</b>