Beispiel für einen Custom Completer
Das Beispiel für einen benutzerdefinierten Vervollständiger zeigt, wie ein Eingabe-Widget auf der Grundlage von Daten, die von einem Modell zur Verfügung gestellt werden, die Vervollständigung von Zeichenketten ermöglicht. Der Completer zeigt Vorschläge für mögliche Wörter an, die auf den ersten drei vom Benutzer eingegebenen Zeichen basieren, und das vom Benutzer gewählte Wort wird mit Hilfe von QTextCursor in TextEdit
eingefügt.
Einrichten der Ressourcendatei
Das Beispiel für den Custom Completer erfordert eine Ressourcendatei, wordlist.txt, die eine Liste von Wörtern enthält, die QCompleter bei der Vervollständigung von Wörtern helfen. Diese Datei enthält das Folgende:
<!DOCTYPE RCC><RCC version="1.0"> <qresource prefix="/"> <file>resources/wordlist.txt</file> </qresource> </RCC>
TextEdit-Klassendefinition
Die Klasse TextEdit
ist eine Unterklasse von QTextEdit mit einem benutzerdefinierten Steckplatz insertCompletion()
und implementiert die Funktionen keyPressEvent() und focusInEvent() neu. TextEdit
enthält auch eine private Funktion textUnderCursor()
und eine private Instanz von QCompleter, c
.
class TextEdit : public QTextEdit { Q_OBJECT public: TextEdit(QWidget *parent = nullptr); ~TextEdit(); void setCompleter(QCompleter *c); QCompleter *completer() const; protected: void keyPressEvent(QKeyEvent *e) override; void focusInEvent(QFocusEvent *e) override; private slots: void insertCompletion(const QString &completion); private: QString textUnderCursor() const; private: QCompleter *c = nullptr; };
Implementierung der TextEdit-Klasse
Der Konstruktor für TextEdit
erstellt ein TextEdit
mit einem Parent und initialisiert c
. Die Anweisungen zur Verwendung der Vervollständigung werden auf dem Objekt TextEdit
mit der Funktion setPlainText() angezeigt.
TextEdit::TextEdit(QWidget *parent) : QTextEdit(parent) { setPlainText(tr("This TextEdit provides autocompletions for words that have more than" " 3 characters. You can trigger autocompletion using ") + QKeySequence("Ctrl+E").toString(QKeySequence::NativeText)); }
Darüber hinaus enthält TextEdit
auch einen Standard-Destruktor:
TextEdit::~TextEdit() { }
Die Funktion setCompleter()
nimmt ein completer entgegen und richtet es ein. Wir verwenden if (c)
, um zu prüfen, ob c
initialisiert wurde. Wenn es initialisiert wurde, wird die Funktion QObject::disconnect() aufgerufen, um das Signal vom Slot zu trennen. Damit soll sichergestellt werden, dass kein vorheriges Completter-Objekt noch mit dem Slot verbunden ist.
void TextEdit::setCompleter(QCompleter *completer) { if (c) c->disconnect(this); c = completer; if (!c) return; c->setWidget(this); c->setCompletionMode(QCompleter::PopupCompletion); c->setCaseSensitivity(Qt::CaseInsensitive); QObject::connect(c, QOverload<const QString &>::of(&QCompleter::activated), this, &TextEdit::insertCompletion); }
Anschließend wird c
mit completer instanziiert und als Widget von TextEdit
festgelegt. Der Vervollständigungsmodus und die Groß-/Kleinschreibung werden ebenfalls eingestellt und dann verbinden wir das Signal activated() mit dem Slot insertCompletion()
.
Die Funktion completer()
ist eine Getter-Funktion, die c
zurückgibt.
QCompleter *TextEdit::completer() const { return c; }
Die Vervollständigungsfunktion zeigt die verfügbaren Optionen an, die auf dem Inhalt von wordlist.txt basieren, aber der Textcursor ist dafür verantwortlich, die fehlenden Zeichen entsprechend der Wortwahl des Benutzers auszufüllen.
Angenommen, der Benutzer gibt "ACT" ein und akzeptiert den Vorschlag des Vervollständigers "ACTUAL". Die Zeichenfolge completion
wird dann durch das Signal activated() des Vervollständigers an insertCompletion()
gesendet.
Die Funktion insertCompletion()
ist für die Vervollständigung des Wortes mit einem QTextCursor Objekt, tc
, zuständig. Sie überprüft, ob das Widget des Vervollständigers TextEdit
ist, bevor sie tc
verwendet, um die zusätzlichen Zeichen zur Vervollständigung des Wortes einzufügen.
void TextEdit::insertCompletion(const QString &completion) { if (c->widget() != this) return; QTextCursor tc = textCursor(); int extra = completion.length() - c->completionPrefix().length(); tc.movePosition(QTextCursor::Left); tc.movePosition(QTextCursor::EndOfWord); tc.insertText(completion.right(extra)); setTextCursor(tc); }
Die folgende Abbildung veranschaulicht diesen Vorgang:
completion.length()
= 6
c->completionPrefix().length()
=3
Die Differenz zwischen diesen beiden Werten ist extra
, die 3 beträgt. Das bedeutet, dass die letzten drei Zeichen von rechts, "U", "A" und "L", von tc
eingefügt werden.
Die Funktion textUnderCursor()
verwendet eine QTextCursor, tc
, um ein Wort unter dem Cursor auszuwählen und es zurückzugeben.
QString TextEdit::textUnderCursor() const { QTextCursor tc = textCursor(); tc.select(QTextCursor::WordUnderCursor); return tc.selectedText(); }
Die Klasse TextEdit
reimplementiert die Funktion focusInEvent(), die als Event-Handler verwendet wird, um Tastatur-Fokus-Ereignisse für das Widget zu empfangen.
void TextEdit::focusInEvent(QFocusEvent *e) { if (c) c->setWidget(this); QTextEdit::focusInEvent(e); }
Die Funktion keyPressEvent() wurde neu implementiert, um Tastenereignisse wie Qt::Key_Enter, Qt::Key_Return, Qt::Key_Escape, Qt::Key_Tab und Qt::Key_Backtab zu ignorieren, so dass der Vervollständiger sie verarbeiten kann.
Wenn es ein aktives Vervollständigungsprogramm gibt, können wir die Tastenkombination Strg+E nicht verarbeiten.
void TextEdit::keyPressEvent(QKeyEvent *e) { if (c && c->popup()->isVisible()) { // The following keys are forwarded by the completer to the widget switch (e->key()) { case Qt::Key_Enter: case Qt::Key_Return: case Qt::Key_Escape: case Qt::Key_Tab: case Qt::Key_Backtab: e->ignore(); return; // let the completer do default behavior default: break; } } const bool isShortcut = (e->modifiers().testFlag(Qt::ControlModifier) && e->key() == Qt::Key_E); // CTRL+E if (!c || !isShortcut) // do not process the shortcut when we have a completer QTextEdit::keyPressEvent(e);
Wir behandeln auch andere Modifikatoren und Tastenkombinationen, auf die das Kompilierprogramm nicht reagieren soll.
const bool ctrlOrShift = e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::ShiftModifier); if (!c || (ctrlOrShift && e->text().isEmpty())) return; static QString eow("~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="); // end of word const bool hasModifier = (e->modifiers() != Qt::NoModifier) && !ctrlOrShift; QString completionPrefix = textUnderCursor(); if (!isShortcut && (hasModifier || e->text().isEmpty()|| completionPrefix.length() < 3 || eow.contains(e->text().right(1)))) { c->popup()->hide(); return; } if (completionPrefix != c->completionPrefix()) { c->setCompletionPrefix(completionPrefix); c->popup()->setCurrentIndex(c->completionModel()->index(0, 0)); } QRect cr = cursorRect(); cr.setWidth(c->popup()->sizeHintForColumn(0) + c->popup()->verticalScrollBar()->sizeHint().width()); c->complete(cr); // popup it up! }
Schließlich wird die Vervollständigung eingeblendet.
Definition der Klasse MainWindow
Die Klasse MainWindow
ist eine Unterklasse von QMainWindow und implementiert einen privaten Slot, about()
. Diese Klasse verfügt auch über zwei private Funktionen, createMenu()
und modelFromFile()
, sowie über private Instanzen von QCompleter und TextEdit
.
class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); private slots: void about(); private: void createMenu(); QAbstractItemModel *modelFromFile(const QString& fileName); QCompleter *completer = nullptr; TextEdit *completingTextEdit; };
Implementierung der Klasse MainWindow
Der Konstruktor konstruiert ein MainWindow
mit einem Elternteil und initialisiert das completer
. Er instanziiert auch ein TextEdit
und setzt dessen Komplementär. Ein QStringListModel, das von modelFromFile()
stammt, wird verwendet, um das completer
zu füllen. Das zentrale Widget von MainWindow
wird auf TextEdit
und seine Größe auf 500 x 300 gesetzt.
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { createMenu(); completingTextEdit = new TextEdit; completer = new QCompleter(this); completer->setModel(modelFromFile(":/resources/wordlist.txt")); completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel); completer->setCaseSensitivity(Qt::CaseInsensitive); completer->setWrapAround(false); completingTextEdit->setCompleter(completer); setCentralWidget(completingTextEdit); resize(500, 300); setWindowTitle(tr("Completer")); }
Die Funktion createMenu()
erstellt die erforderlichen QAction Objekte, die für die Menüs "Datei" und "Hilfe" benötigt werden, und ihre triggered()-Signale werden mit den Steckplätzen quit()
, about()
bzw. aboutQt()
verbunden.
void MainWindow::createMenu() { QAction *exitAction = new QAction(tr("Exit"), this); QAction *aboutAct = new QAction(tr("About"), this); QAction *aboutQtAct = new QAction(tr("About Qt"), this); connect(exitAction, &QAction::triggered, qApp, &QApplication::quit); connect(aboutAct, &QAction::triggered, this, &MainWindow::about); connect(aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt); QMenu *fileMenu = menuBar()->addMenu(tr("File")); fileMenu->addAction(exitAction); QMenu *helpMenu = menuBar()->addMenu(tr("About")); helpMenu->addAction(aboutAct); helpMenu->addAction(aboutQtAct); }
Die Funktion modelFromFile()
nimmt eine fileName entgegen und versucht, den Inhalt dieser Datei in eine QStringListModel zu extrahieren. Wir zeigen die Qt::WaitCursor an, wenn wir die QStringList, words
auffüllen, und stellen den Mauszeiger wieder her, wenn wir fertig sind.
QAbstractItemModel *MainWindow::modelFromFile(const QString& fileName) { QFile file(fileName); if (!file.open(QFile::ReadOnly)) return new QStringListModel(completer); #ifndef QT_NO_CURSOR QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); #endif QStringList words; while (!file.atEnd()) { QByteArray line = file.readLine(); if (!line.isEmpty()) words << QString::fromUtf8(line.trimmed()); } #ifndef QT_NO_CURSOR QGuiApplication::restoreOverrideCursor(); #endif return new QStringListModel(words, completer); }
Die Funktion about()
liefert eine kurze Beschreibung des Custom Completer-Beispiels.
void MainWindow::about() { QMessageBox::about(this, tr("About"), tr("This example demonstrates the " "different features of the QCompleter class.")); }
main()
Funktion
Die Funktion main()
instanziiert MainWindow
und ruft die Funktion show() auf.
int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow window; window.show(); return app.exec(); }
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.