Completer-Beispiel
Das Completer-Beispiel zeigt, wie man die Vervollständigung von Zeichenketten für ein Eingabewidget auf der Grundlage der von einem Modell bereitgestellten Daten ermöglicht.
Dieses Beispiel verwendet ein benutzerdefiniertes Elementmodell, FileSystemModel
, und ein QCompleter Objekt. QCompleter ist eine Klasse, die Vervollständigungen basierend auf einem Elementmodell bereitstellt. Die Art des Modells, der Vervollständigungsmodus und die Groß- und Kleinschreibung können über Kombinationsfelder ausgewählt werden.
Die Ressourcendatei
Für das Completer-Beispiel wird eine Ressourcendatei benötigt, um die countries.txt und words.txt zu speichern. Die Ressourcendatei enthält den folgenden Code:
<!DOCTYPE RCC><RCC version="1.0"> <qresource prefix="/"> <file>resources/countries.txt</file> <file>resources/wordlist.txt</file> </qresource> </RCC>
FileSystemModel Klassendefinition
Die Klasse FileSystemModel
ist eine Unterklasse von QFileSystemModel, die ein Datenmodell für das lokale Dateisystem bereitstellt.
class FileSystemModel : public QFileSystemModel { public: FileSystemModel(QObject *parent = nullptr); QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; };
Diese Klasse hat nur einen Konstruktor und eine Funktion data()
, da sie nur erstellt wurde, um data()
in die Lage zu versetzen, den gesamten Dateipfad für die Anzeigerolle zurückzugeben, im Gegensatz zu QFileSystemModel's data()
Funktion, die nur den Ordner und nicht die Laufwerksbezeichnung zurückgibt. Dies wird in der Implementierung von FileSystemModel
näher erläutert.
Implementierung der FileSystemModel-Klasse
Der Konstruktor für die Klasse FileSystemModel
wird verwendet, um parent an QFileSystemModel zu übergeben.
FileSystemModel::FileSystemModel(QObject *parent) : QFileSystemModel(parent) { }
Wie bereits erwähnt, wird die Funktion data()
reimplementiert, damit sie den gesamten Dateipfad für die Anzeigerolle zurückgibt. Mit QFileSystemModel sehen Sie zum Beispiel "Programme" in der Ansicht. Mit FileSystemModel
wird jedoch "C:\Programmdateien" angezeigt.
QVariant FileSystemModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole && index.column() == 0) { QString path = QDir::toNativeSeparators(filePath(index)); if (path.endsWith(QDir::separator())) path.chop(1); return path; } return QFileSystemModel::data(index, role); }
Die Qt::EditRole, die QCompleter für die Suche nach Übereinstimmungen verwendet, bleibt unverändert.
Definition der Klasse MainWindow
Die Klasse MainWindow
ist eine Unterklasse von QMainWindow und implementiert fünf private Slots - about()
, changeCase()
, changeMode()
, changeModel()
, und changeMaxVisible()
.
class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); private slots: void about(); void changeCase(int); void changeMode(int); void changeModel(); void changeMaxVisible(int);
Innerhalb der Klasse MainWindow
haben wir zwei private Funktionen: createMenu()
und modelFromFile()
. Wir deklarieren auch die benötigten privaten Widgets - drei QComboBox Objekte, ein QCheckBox, ein QCompleter, ein QLabel und ein QLineEdit.
private: void createMenu(); QAbstractItemModel *modelFromFile(const QString &fileName); QComboBox *caseCombo = nullptr; QComboBox *modeCombo = nullptr; QComboBox *modelCombo = nullptr; QSpinBox *maxVisibleSpinBox = nullptr; QCheckBox *wrapCheckBox = nullptr; QCompleter *completer = nullptr; QLabel *contentsLabel = nullptr; QLineEdit *lineEdit = nullptr; };
Implementierung der MainWindow-Klasse
Der Konstruktor von MainWindow
konstruiert ein MainWindow
mit einem übergeordneten Widget und initialisiert die privaten Mitglieder. Anschließend wird die Funktion createMenu()
aufgerufen.
Wir richten drei QComboBox Objekte ein, modelComb
, modeCombo
und caseCombo
. Standardmäßig ist modelCombo
auf QFileSystemModel, modeCombo
auf "Filtered Popup" und caseCombo
auf "Case Insensitive" eingestellt.
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { createMenu(); QWidget *centralWidget = new QWidget; QLabel *modelLabel = new QLabel; modelLabel->setText(tr("Model")); modelCombo = new QComboBox; modelCombo->addItem(tr("QFileSystemModel")); modelCombo->addItem(tr("QFileSystemModel that shows full path")); modelCombo->addItem(tr("Country list")); modelCombo->addItem(tr("Word list")); modelCombo->setCurrentIndex(0); QLabel *modeLabel = new QLabel; modeLabel->setText(tr("Completion Mode")); modeCombo = new QComboBox; modeCombo->addItem(tr("Inline")); modeCombo->addItem(tr("Filtered Popup")); modeCombo->addItem(tr("Unfiltered Popup")); modeCombo->setCurrentIndex(1); QLabel *caseLabel = new QLabel; caseLabel->setText(tr("Case Sensitivity")); caseCombo = new QComboBox; caseCombo->addItem(tr("Case Insensitive")); caseCombo->addItem(tr("Case Sensitive")); caseCombo->setCurrentIndex(0);
Die maxVisibleSpinBox
wird erstellt und bestimmt die Anzahl der sichtbaren Elemente im Completter
Anschließend wird die wrapCheckBox
erstellt. Diese checkBox
bestimmt, ob die Eigenschaft setWrapAround() von completer
aktiviert oder deaktiviert ist.
QLabel *maxVisibleLabel = new QLabel; maxVisibleLabel->setText(tr("Max Visible Items")); maxVisibleSpinBox = new QSpinBox; maxVisibleSpinBox->setRange(3,25); maxVisibleSpinBox->setValue(10); wrapCheckBox = new QCheckBox; wrapCheckBox->setText(tr("Wrap around completions")); wrapCheckBox->setChecked(true);
Wir instanziieren contentsLabel
und setzen seine Größenpolitik auf fixed. Die Signale der Kombinationsfelder activated() werden dann mit ihren jeweiligen Steckplätzen verbunden.
contentsLabel = new QLabel; contentsLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(modelCombo, &QComboBox::activated, this, &MainWindow::changeModel); connect(modeCombo, &QComboBox::activated, this, &MainWindow::changeMode); connect(caseCombo, &QComboBox::activated, this, &MainWindow::changeCase); connect(maxVisibleSpinBox, &QSpinBox::valueChanged, this, &MainWindow::changeMaxVisible);
Die lineEdit
wird eingerichtet und dann ordnen wir alle Widgets mit einer QGridLayout an. Die changeModel()
Funktion wird aufgerufen, um die completer
zu initialisieren.
lineEdit = new QLineEdit; QGridLayout *layout = new QGridLayout; layout->addWidget(modelLabel, 0, 0); layout->addWidget(modelCombo, 0, 1); layout->addWidget(modeLabel, 1, 0); layout->addWidget(modeCombo, 1, 1); layout->addWidget(caseLabel, 2, 0); layout->addWidget(caseCombo, 2, 1); layout->addWidget(maxVisibleLabel, 3, 0); layout->addWidget(maxVisibleSpinBox, 3, 1); layout->addWidget(wrapCheckBox, 4, 0); layout->addWidget(contentsLabel, 5, 0, 1, 2); layout->addWidget(lineEdit, 6, 0, 1, 2); centralWidget->setLayout(layout); setCentralWidget(centralWidget); changeModel(); setWindowTitle(tr("Completer")); lineEdit->setFocus(); }
Die Funktion createMenu()
wird verwendet, um die QAction Objekte zu instanziieren, die benötigt werden, um die fileMenu
und helpMenu
zu füllen. Die triggered()-Signale der Aktionen sind mit ihren jeweiligen Slots 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 die fileName einer Datei entgegen und verarbeitet sie abhängig von ihrem Inhalt.
Zunächst wird die file
validiert, um sicherzustellen, dass sie im Modus QFile::ReadOnly geöffnet werden kann. Ist dies nicht der Fall, gibt die Funktion ein leeres QStringListModel zurück.
QAbstractItemModel *MainWindow::modelFromFile(const QString &fileName) { QFile file(fileName); if (!file.open(QFile::ReadOnly)) return new QStringListModel(completer);
Der Mauszeiger wird dann mit Qt::WaitCursor überschrieben, bevor wir ein QStringList Objekt, words
, mit dem Inhalt von file
füllen. Danach stellen wir den Mauszeiger wieder her.
#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
Wie bereits erwähnt, enthält die Ressourcendatei zwei Dateien - countries.txt und words.txt. Wenn file
words.txt lautet, geben wir QStringListModel mit words
als QStringList und completer
als übergeordnetes Element zurück.
if (!fileName.contains(QLatin1String("countries.txt"))) return new QStringListModel(words, completer);
Wenn file
countries.txt gelesen wird, benötigen wir QStandardItemModel mit words.count()
Zeilen, 2 Spalten und completer
als übergeordnetes Element.
QStandardItemModel *m = new QStandardItemModel(words.count(), 2, completer);
Eine Standardzeile in countries.txt ist:
Norwegen NEIN
Um das Objekt QStandardItemModel, m
, zu füllen, müssen wir also den Ländernamen und sein Symbol aufteilen. Sobald dies geschehen ist, geben wir m
zurück.
for (int i = 0; i < words.count(); ++i) { QModelIndex countryIdx = m->index(i, 0); QModelIndex symbolIdx = m->index(i, 1); QString country = words.at(i).mid(0, words[i].length() - 2).trimmed(); QString symbol = words.at(i).right(2); m->setData(countryIdx, country); m->setData(symbolIdx, symbol); } return m; }
Mit der Funktion changeMode()
wird der Modus von completer
in Abhängigkeit vom Wert von index
eingestellt.
void MainWindow::changeMode(int index) { QCompleter::CompletionMode mode; if (index == 0) mode = QCompleter::InlineCompletion; else if (index == 1) mode = QCompleter::PopupCompletion; else mode = QCompleter::UnfilteredPopupCompletion; completer->setCompletionMode(mode); }
Die Funktion changeModel()
ändert das verwendete Elementmodell auf der Grundlage des vom Benutzer ausgewählten Modells.
Eine switch
-Anweisung wird verwendet, um das Elementmodell basierend auf dem Index von modelCombo
zu ändern. Wenn case
gleich 0 ist, wird ein unsortiertes QFileSystemModel verwendet, das uns einen Dateipfad ohne die Laufwerksbezeichnung liefert.
void MainWindow::changeModel() { delete completer; completer = new QCompleter(this); completer->setMaxVisibleItems(maxVisibleSpinBox->value()); switch (modelCombo->currentIndex()) { default: case 0: { // Unsorted QFileSystemModel QFileSystemModel *fsModel = new QFileSystemModel(completer); fsModel->setRootPath(QString()); completer->setModel(fsModel); contentsLabel->setText(tr("Enter file path")); } break;
Beachten Sie, dass wir das Modell mit completer
als übergeordnetes Modell erstellen, da dies uns erlaubt, das Modell durch ein neues Modell zu ersetzen. Die completer
sorgt dafür, dass das alte Modell gelöscht wird, sobald ihm ein neues Modell zugewiesen wird.
Wenn case
gleich 1 ist, verwenden wir DirModel
, das wir zuvor definiert haben, was zu vollständigen Pfaden für die Dateien führt.
case 1: { // FileSystemModel that shows full paths FileSystemModel *fsModel = new FileSystemModel(completer); completer->setModel(fsModel); fsModel->setRootPath(QString()); contentsLabel->setText(tr("Enter file path")); } break;
Wenn case
gleich 2 ist, versuchen wir, die Namen der Länder zu vervollständigen. Dazu ist ein Objekt QTreeView erforderlich, treeView
. Die Ländernamen werden aus countries.txt extrahiert und das Popup, das zur Anzeige der Vervollständigungen verwendet wird, auf treeView
gesetzt.
case 2: { // Country List completer->setModel(modelFromFile(":/resources/countries.txt")); QTreeView *treeView = new QTreeView; completer->setPopup(treeView); treeView->setRootIsDecorated(false); treeView->header()->hide(); treeView->header()->setStretchLastSection(false); treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch); treeView->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); contentsLabel->setText(tr("Enter name of your country")); } break;
Der folgende Screenshot zeigt den Completer mit dem Länderlistenmodell.
Wenn case
gleich 3 ist, versuchen wir, Wörter zu vervollständigen. Dies geschieht mit Hilfe eines QStringListModel, das Daten aus words.txt enthält. Das Modell ist nach case insensitively sortiert.
Der unten stehende Screenshot zeigt den Completer mit dem Wortlistenmodell.
Sobald der Modelltyp ausgewählt ist, rufen wir die Funktionen changeMode()
und changeCase()
auf und setzen die Option wrap entsprechend. Das Signal clicked() von wrapCheckBox
ist mit dem Steckplatz setWrapAround() von completer
verbunden.
case 3: { // Word list completer->setModel(modelFromFile(":/resources/wordlist.txt")); completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel); contentsLabel->setText(tr("Enter a word")); } break; } changeMode(modeCombo->currentIndex()); changeCase(caseCombo->currentIndex()); completer->setWrapAround(wrapCheckBox->isChecked()); lineEdit->setCompleter(completer); connect(wrapCheckBox, &QAbstractButton::clicked, completer, &QCompleter::setWrapAround); }
Die Funktion changeMaxVisible()
aktualisiert die maximale Anzahl der sichtbaren Elemente im Completer.
void MainWindow::changeMaxVisible(int max) { completer->setMaxVisibleItems(max); }
Die Funktion about()
liefert eine kurze Beschreibung des 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 QApplication und 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.