简体   繁体   English

用于 QLineEdit 的 PyQt5 QCompleter 崩溃,没有异常可见

[英]PyQt5 QCompleter for QLineEdit crashing with no exception visible

I'm trying to use the QCompleter class for the QLineEdit to give auto completion suggestions while typing, and update the suggestions after the user enters a new text.我正在尝试使用 QLineEdit 的 QCompleter 类在键入时提供自动完成建议,并在用户输入新文本后更新建议。 But when I try to update the Completer with text that starts with something that is already at the completer list, it just crashes the entire app with no visible exception!但是,当我尝试使用以完成者列表中已有内容开头的文本更新完成者时,它只会使整个应用程序崩溃,而没有可见的异常! Even try-except doesn't catch this error, and I can't understand what I am doing wrong...甚至 try-except 也没有捕捉到这个错误,我无法理解我做错了什么......

Below is a simpler example of my code: it is a simple "echo" console application that gets commands from QLineEdit (input text box) and writing it to QTextBrowser (output text box).下面是我的代码的一个更简单的示例:它是一个简单的“echo”控制台应用程序,它从 QLineEdit(输入文本框)获取命令并将其写入 QTextBrowser(输出文本框)。 When entering entirely new "command" (text) it works fine, and being added to the completer, so next time I can see it.当输入全新的“命令”(文本)时,它工作正常,并被添加到完成器中,所以下次我可以看到它。 But if the new text starts similar to other words in the completer list, choosing it crashes the entire GUI app with no exception visible, not even when I'm running in debug mode...但是,如果新文本的开头与完成列表中的其他单词相似,则选择它会使整个 GUI 应用程序崩溃,没有任何异常可见,即使我在调试模式下运行也是如此...

Please see my example below, and try writing at the upper text box options like: a, aa, aaa (that start similar to completer already word: aaa1)请参见我下面的示例,并尝试在上方的文本框选项中书写,例如:a、aa、aaa(开头类似于完成者已经单词:aaa1)

What am I doing wrong??我究竟做错了什么??

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QVBoxLayout, QLineEdit, QTextBrowser, QCompleter

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

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

        # Create text box for input
        self.consoleCommandLineEdit = QLineEdit(self)
        self.consoleCommandLineEdit.setFixedHeight(25)
        self.consoleCommandLineEdit.editingFinished.connect(self.gotConsoleCommand)
        self.completerCommands = ['aaa1','aaa2','aaa3'] # initial completer list
        completer = QCompleter(self.completerCommands)
        self.consoleCommandLineEdit.setCompleter(completer)

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

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

    def gotConsoleCommand(self):
        cmd = self.consoleCommandLineEdit.text()
        self.consoleCommandLineEdit.setText('')
        self.sendCommandToConsole(cmd)

    def sendCommandToConsole(self,cmd):
        self.consoleViewer.append(cmd) # add cmd to output box
        if cmd not in self.completerCommands: # if the command is new, add it to the completer
            self.completerCommands.append(cmd)                  # 1. add the new text to the list we have
            completer = QCompleter(self.completerCommands)      # 2. create a new completer object
            self.consoleCommandLineEdit.setCompleter(completer) # 3. set the new completer as the LineEdit completer


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

I have not yet found the cause of the problem but a better solution than creating a new QCompleter every time you need to add a new text.我还没有找到问题的原因,但是比每次需要添加新文本时都创建一个新的 QCompleter 更好的解决方案。 In this case it is better to use a model to store the texts that is the basis of the QCompleter information.在这种情况下,最好使用模型来存储作为 QCompleter 信息基础的文本。

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(text) for text in ("aaa1", "aaa2", "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.sendCommandToConsole(cmd)

    def sendCommandToConsole(self, cmd):
        self.consoleViewer.append(cmd)  # add cmd to output box
        if not self.model.findItems(cmd):
            self.model.appendRow(QStandardItem(cmd))


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

Perhaps something that helps us understand the problem is that if you add a parent to QCompleter the problem does not happen:也许可以帮助我们理解问题的是,如果您将父级添加到 QCompleter,则问题不会发生:

completer = QCompleter(self.completerCommands, self)

but I stress: the best solution is to use a model.但我强调:最好的解决方案是使用模型。

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

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