Exemple de Completer
L'exemple Completer montre comment fournir des fonctionnalités de complétion de chaînes de caractères pour un widget de saisie en s'appuyant sur les données fournies par un modèle.

Cet exemple utilise un modèle d’éléments personnalisé, FileSystemModel, et un objet QCompleter. QCompleter est une classe qui fournit des suggestions de complétion basées sur un modèle d’éléments. Le type de modèle, le mode de complétion et la sensibilité à la casse peuvent être sélectionnés à l’aide de listes déroulantes.
Le fichier de ressources
L’exemple Completer nécessite un fichier de ressources afin de stocker les fichiers countries.txt et words.txt. Le fichier de ressources contient le code suivant :
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>resources/countries.txt</file>
<file>resources/wordlist.txt</file>
</qresource>
</RCC>Définition de la classe FileSystemModel
La classe ` FileSystemModel ` est une sous-classe de ` QFileSystemModel`, qui fournit un modèle de données pour le système de fichiers local.
class FileSystemModel : public QFileSystemModel
{
public:
FileSystemModel(QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
};Cette classe ne dispose que d’un constructeur et d’une fonction ` data() `, car elle est uniquement créée pour permettre à ` data() ` de renvoyer le chemin d’accès complet au fichier pour le rôle d’affichage, contrairement à la fonction ` data() ` de ` QFileSystemModel`, qui ne renvoie que le dossier et non le nom du lecteur. Ceci est expliqué plus en détail dans l’implémentation de ` FileSystemModel`.
Implémentation de la classe FileSystemModel
Le constructeur de la classe FileSystemModel sert à transmettre parent à QFileSystemModel.
FileSystemModel::FileSystemModel(QObject *parent)
: QFileSystemModel(parent)
{
}Comme mentionné précédemment, la fonction ` data() ` est réimplémentée afin qu’elle renvoie le chemin d’accès complet du fichier pour l’affichage. Par exemple, avec ` QFileSystemModel`, vous verrez « Program Files » s’afficher. En revanche, avec ` FileSystemModel`, vous verrez « C:\Program Files ».
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);
}La méthode ` Qt::EditRole`, que ` QCompleter ` utilise pour rechercher des correspondances, reste inchangée.
Définition de la classe MainWindow
La classe « MainWindow » est une sous-classe de « QMainWindow » et implémente cinq slots privés : « about() », « changeCase() », « changeMode() », « changeModel() » et « 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);Au sein de la classe ` MainWindow `, nous disposons de deux fonctions privées : ` createMenu() ` et ` modelFromFile()`. Nous déclarons également les widgets privés nécessaires : trois objets ` QComboBox `, un ` QCheckBox`, un ` QCompleter`, un ` QLabel` et un ` 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;
};Implémentation de la classe MainWindow
Le constructeur de ` MainWindow ` crée un ` MainWindow ` avec un widget parent et initialise les membres privés. La fonction ` createMenu() ` est ensuite appelée.
Nous configurons trois objets ` QComboBox ` : ` modelComb`, ` modeCombo ` et ` caseCombo`. Par défaut, le ` modelCombo ` est défini sur ` QFileSystemModel`, le ` modeCombo ` sur « Filtered Popup » et le ` caseCombo ` sur « Case Insensitive ».
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);La variable « maxVisibleSpinBox » est créée et détermine le nombre d'éléments visibles dans la liste de complétion
L’ wrapCheckBox est ensuite configuré. Ce checkBox détermine si la propriété setWrapAround() de l’ completer est activée ou désactivée.
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);Nous instancions contentsLabel et définissons sa politique de taille sur fixed. Les signaux activated() des listes déroulantes sont ensuite connectés à leurs slots respectifs.
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);L’ lineEdit est configuré, puis nous organisons tous les widgets à l’aide d’un QGridLayout. La fonction changeModel() est appelée pour initialiser l’ completer.
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();
}La fonction ` createMenu() ` sert à instancier les objets ` QAction ` nécessaires pour remplir la ` fileMenu ` et la ` helpMenu`. Les signaux ` triggered()` des actions sont connectés à leurs slots respectifs.
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);
}La fonction modelFromFile() accepte l’ fileName d’un fichier et le traite en fonction de son contenu.
file Nous validons d’abord le QStringListModel pour nous assurer qu’il peut être ouvert en mode QFile::ReadOnly. En cas d’échec, la fonction renvoie un vide.
QAbstractItemModel *MainWindow::modelFromFile(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QFile::ReadOnly))
return new QStringListModel(completer);Le curseur de la souris est ensuite remplacé par Qt::WaitCursor avant de remplir un objet QStringList, words, avec le contenu de file. Une fois cette opération terminée, nous rétablissons le curseur de la souris.
#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();
#endifComme mentionné précédemment, le fichier de ressources contient deux fichiers : countries.txt et words.txt. Si la valeur lue dans file est words.txt, nous renvoyons un QStringListModel dont le QStringList est words et dont le parent est completer.
if (!fileName.contains(QLatin1String("countries.txt")))
return new QStringListModel(words, completer);Si le fichier lu par la fonction ` file ` est `countries.txt`, nous avons alors besoin d’un tableau ` QStandardItemModel ` comportant ` words.count() ` lignes, `2` colonnes et ` completer ` comme parent.
QStandardItemModel *m = new QStandardItemModel(words.count(), 2, completer);Une ligne type dans le fichier « countries.txt » est la suivante :
Norvège NO
Par conséquent, pour remplir l'objet « QStandardItemModel », m, nous devons séparer le nom du pays et son code. Une fois cette opération effectuée, nous renvoyons m.
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;
}La fonction ` changeMode() ` définit le mode de l'completer, en fonction de la valeur de ` index`.
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);
}La fonction ` changeModel() ` modifie le modèle d’élément utilisé en fonction du modèle sélectionné par l’utilisateur.
Une instruction ` switch ` est utilisée pour modifier le modèle d’élément en fonction de l’index de ` modelCombo`. Si ` case ` est égal à 0, nous utilisons un modèle non trié ` QFileSystemModel`, ce qui nous fournit un chemin d’accès au fichier excluant le nom du lecteur.
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;Notez que nous créons le modèle en désignant completer comme parent, ce qui nous permet de remplacer ce modèle par un nouveau. L’ completer garantira que l’ancien modèle sera supprimé dès qu’un nouveau modèle lui sera attribué.
Si case vaut 1, nous utilisons l’ DirModel que nous avons défini précédemment, ce qui génère des chemins d’accès complets pour les fichiers.
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;Lorsque case vaut 2, nous tentons de compléter les noms de pays. Cela nécessite un objet « QTreeView », treeView. Les noms de pays sont extraits du fichier countries.txt et la fenêtre contextuelle utilisée pour afficher les suggestions est définie sur treeView.
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;La capture d’écran ci-dessous montre le Completer avec le modèle de liste de pays.

Si la valeur de « case » est 3, nous tentons de compléter des mots. Pour cela, nous utilisons un objet « QStringListModel » contenant des données extraites du fichier «words.txt». Le modèle est trié case insensitively.
La capture d’écran ci-dessous montre le Completer avec le modèle de liste de mots.

Une fois le type de modèle sélectionné, nous appelons la fonction « changeMode() » et la fonction « changeCase() », puis nous configurons l’option « wrap » en conséquence. Le signal « clicked() » de l’« wrapCheckBox » est connecté au slot « setWrapAround() » de l’« completer ».
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);
}La variable changeMaxVisible() met à jour le nombre maximal d’éléments visibles dans le « completer ».
void MainWindow::changeMaxVisible(int max)
{
completer->setMaxVisibleItems(max);
}La fonction « about() » fournit une brève description de l’exemple.
void MainWindow::about()
{
QMessageBox::about(this, tr("About"), tr("This example demonstrates the "
"different features of the QCompleter class."));
}main() Fonction
La fonction main() instancie QApplication et MainWindow, puis appelle la fonction show().
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
window.show();
return app.exec();
}© 2026 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.