Mis à jour le 04/12/2018
  • 50 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Apprenez à utiliser les boîtes de dialogue usuelles

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Après un chapitre sur les signaux et les slots riche en nouveaux concepts, on relâche ici un peu la pression.
Nous allons découvrir les boîtes de dialogue usuelles, aussi appelées common dialogs par nos amis anglophones.

Qu'est-ce qu'une boîte de dialogue usuelle ? C'est une fenêtre qui sert à remplir une fonction bien précise. Par exemple, on connaît la boîte de dialogue « message » qui affiche un message et ne vous laisse d'autre choix que de cliquer sur le bouton OK. Ou encore la boîte de dialogue « ouvrir un fichier », « enregistrer un fichier », « sélectionner une couleur », etc.
On ne s'amuse pas à recréer « à la main » ces fenêtres à chaque fois. On profite de fonctions système pour ouvrir des boîtes de dialogue pré-construites.

De plus, Qt s'adapte à l'OS pour afficher une boîte de dialogue qui corresponde aux formes habituelles de votre OS.

Affichez un message

Le premier type de boîte de dialogue que nous allons voir est le plus courant : la boîte de dialogue « afficher un message ».

Nous allons créer sur notre fenêtre de typeMaFenetreun bouton qui appellera un slot personnalisé. Ce slot ouvrira la boîte de dialogue. En clair, un clic sur le bouton doit pouvoir ouvrir la boîte de dialogue.

Les boîtes de dialogue « afficher un message » sont contrôlées par la classeQMessageBox. Vous pouvez commencer par faire l'includecorrespondant dansMaFenetre.hpour ne pas l'oublier :#include <QMessageBox>.

Quelques rappels et préparatifs

Pour que l'on soit sûr de travailler ensemble sur le même code, je vous donne le code source des fichiersMaFenetre.hetMaFenetre.cppsur lesquels je vais travailler. Ils ont été simplifiés au maximum histoire d'éviter le superflu.

// MaFenetre.h
 
#ifndef DEF_MAFENETRE
#define DEF_MAFENETRE
 
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QMessageBox>
 
class MaFenetre : public QWidget
{
    Q_OBJECT
 
    public:
    MaFenetre();
 
    public slots:
    void ouvrirDialogue();
 
    private:
    QPushButton *m_boutonDialogue;
};
 
#endif
// MaFenetre.cpp
 
#include "MaFenetre.h"
 
MaFenetre::MaFenetre() : QWidget()
{
    setFixedSize(230, 120);
 
    m_boutonDialogue = new QPushButton("Ouvrir la boîte de dialogue", this);
    m_boutonDialogue->move(40, 50);
 
    QObject::connect(m_boutonDialogue, SIGNAL(clicked()), this, SLOT(ouvrirDialogue()));
}
 
void MaFenetre::ouvrirDialogue()
{
    // Vous insérerez ici le code d'ouverture des boîtes de dialogue
}

C'est très simple. Nous avons créé dans la boîte de dialogue un bouton qui appelle le slot personnaliséouvrirDialogue(). C'est dans ce slot que nous nous chargerons d'ouvrir une boîte de dialogue.

Au cas où certains se poseraient la question, notremain.cppn'a pas changé :

// main.cpp
 
#include <QApplication>
#include "MaFenetre.h"
 
 
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
 
    MaFenetre fenetre;
    fenetre.show();
 
    return app.exec();
}

Ouvrez une boîte de dialogue avec une méthode statique

Bien, place à l'action maintenant !

La classe QMessageBoxpermet de créer des objets de typeQMessageBox(comme toute classe qui se respecte) mais on utilise majoritairement ses méthodes statiques, pour des raisons de simplicité. Nous commencerons donc par découvrir les méthodes statiques, qui se comportent (je le rappelle) comme de simples fonctions. Elles ne nécessiteront pas de créer d'objet.

QMessageBox::information

La méthode statique information()permet d'ouvrir une boîte de dialogue constituée d'une icône « information ».
Son prototype est le suivant :

StandardButton information ( QWidget * parent, const QString & title, const QString & text, StandardButtons buttons = Ok, StandardButton defaultButton= NoButton );

Seuls les trois premiers paramètres sont obligatoires, les autres ayant, comme vous le voyez, des valeurs par défaut.
Ces trois premiers paramètres sont :

  • parent: un pointeur vers la fenêtre parente (qui doit être de typeQWidgetou hériter deQWidget). Vous pouvez envoyerNULLen paramètre si vous ne voulez pas que votre boîte de dialogue ait une fenêtre parente, mais ce sera plutôt rare.

  • title: le titre de la boîte de dialogue (affiché en haut de la fenêtre).

  • text: le texte affiché au sein de la boîte de dialogue.

Testons donc un code très simple. Voici le code du slot ouvrirDialogue():

void MaFenetre::ouvrirDialogue()
{
    QMessageBox::information(this, "Titre de la fenêtre", "Bonjour et bienvenueà tous les Zéros !");
}

L'appel de la méthode statique se fait donc comme celui d'une fonction classique, à la différence près qu'il faut mettre en préfixe le nom de la classe dans laquelle elle est définie (d'où leQMessageBox::avant).

Le résultat est une boîte de dialogue comme vous avez l'habitude d'en voir, constituée d'un bouton OK :

Boîte de dialogue information
Boîte de dialogue information

Comble du raffinement, il est même possible de mettre en forme son message à l'aide de balises (X)HTML, pour ceux qui connaissent.

Exemple de boîte de dialogue « enrichie » avec du code HTML :

QMessageBox::information(this, "Titre de la fenêtre", "Bonjour et bienvenue à<strong>tous les Zéros !</strong>");
Boîte de dialogue information avec HTML
Boîte de dialogue information avec HTML
QMessageBox::warning

Si la boîte de dialogue « information » sert à informer l'utilisateur par un message, la boîte de dialoguewarningle met en garde contre quelque chose. Elle est généralement accompagné d'un « ding » caractéristique.

Elle s'utilise de la même manière queQMessageBox::informationmais, cette fois, l'icône change :

QMessageBox::warning(this, "Titre de la fenêtre", "Attention, vous êtes peut-être un Zéro !");
Boîte de dialogue attention
Boîte de dialogue attention
QMessageBox::critical

Quand c'est trop tard et qu'une erreur s'est produite, il ne vous reste plus qu'à utiliser la méthode statiquecritical():

QMessageBox::critical(this, "Titre de la fenêtre", "Vous n'êtes pas un Zéro, sortez d'ici ou j'appelle la police !");
Boîte de dialogue erreur critique
Boîte de dialogue erreur critique
QMessageBox::question

Si vous avez une question à poser à l'utilisateur, c'est la boîte de dialogue qu'il vous faut !

QMessageBox::question(this, "Titre de la fenêtre", "Dites voir, je me posais la question comme cela, êtes-vous vraiment un Zéro ?");
Boîte de dialogue question
Boîte de dialogue question

C'est bien joli mais… comment peut-on répondre à la question avec un simple bouton OK ?

Par défaut, c'est toujours un bouton OK qui s'affiche. Mais dans certains cas, comme lorsqu'on pose une question, il faudra afficher d'autres boutons pour que la boîte de dialogue ait du sens.

Personnalisez les boutons de la boîte de dialogue

Pour personnaliser les boutons de la boîte de dialogue, il faut utiliser le quatrième paramètre de la méthode statique. Ce paramètre accepte une combinaison de valeurs prédéfinies, séparées par un OR (la barre verticale|). On appelle cela des flags.

La liste des flags disponibles est donnée par la documentation. Comme vous pouvez le voir, vous avez du choix.
Si on veut placer les boutons « Oui » et « Non », il nous suffit de combiner les valeursQMessageBox::YesetQMessageBox::No.

QMessageBox::question(this, "Titre de la fenêtre", "Dites voir, je me posais la question comme cela, êtes-vous vraiment un Zéro ?", QMessageBox::Yes | QMessageBox::No);

Les boutons apparaissent alors :

Boîte de dialogue question avec les boutons
Boîte de dialogue question avec les boutons

Horreur ! Malédiction ! Enfer et damnation !
L'anglais me poursuit, les boutons sont écrits en anglais. Catastrophe, qu'est-ce que je vais faire, au secouuuuuurs !!!

En effet, les boutons sont écrits en anglais. Mais ce n'est pas grave du tout, les applications Qt peuvent être facilement traduites.

On ne va pas entrer dans les détails du fonctionnement de la traduction. Je vais vous donner un code à placer dans le fichier main.cppet vous allez l'utiliser gentiment sans poser de questions. ;)

// main.cpp
 
#include <QApplication>
#include <QTranslator>
#include <QLocale>
#include <QLibraryInfo>
#include "MaFenetre.h"
 
 
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
 
    QString locale = QLocale::system().name().section('_', 0, 0);
    QTranslator translator;
    translator.load(QString("qt_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
    app.installTranslator(&translator);
 
    MaFenetre fenetre;
    fenetre.show();
 
    return app.exec();
}

Les lignes ajoutées ont été surlignées. Il y a plusieurs includeset quelques lignes de code supplémentaires dans le main.
Normalement, votre application devrait maintenant afficher des boutons en français :

Boîte de dialogue question en français
Boîte de dialogue question en français

Et voilà le travail !

C'est cool, mais comment je fais pour savoir sur quel bouton l'utilisateur a cliqué ?

Cette question est pertinente, il faut que j'y réponde. :)

Récupérez la valeur de retour de la boîte de dialogue

Les méthodes statiques que nous venons de voir renvoient un entier (int). On peut tester facilement la signification de ce nombre à l'aide des valeurs prédéfinies par Qt.

void MaFenetre::ouvrirDialogue()
{
    int reponse = QMessageBox::question(this, "Interrogatoire", "Dites voir, je me posais la question comme cela, êtes-vous vraiment un Zéro ?", QMessageBox ::Yes | QMessageBox::No);
 
    if (reponse == QMessageBox::Yes)
    {
        QMessageBox::information(this, "Interrogatoire", "Alors bienvenue chezles Zéros !");
    }
    else if (reponse == QMessageBox::No)
    {
        QMessageBox::critical(this, "Interrogatoire", "Tricheur ! Menteur ! Voleur ! Ingrat ! Lâche ! Traître !\nSors d'ici ou j'appelle la police !");
    }
}

Voici un schéma de ce qui peut se passer :

Traitement du retour de la boîte de dialogue
Traitement du retour de la boîte de dialogue

C'est ma foi clair, non ?

Saisissez une information

Les boîtes de dialogue précédentes étaient un peu limitées car, à part présenter différents boutons, on ne pouvait pas trop interagir avec l'utilisateur.

Si vous souhaitez que votre utilisateur saisisse une information, ou encore fasse un choix parmi une liste, les boîtes de dialogue de saisie sont idéales. Elles sont gérées par la classe QInputDialog, que je vous conseille d'inclure dès maintenant dans MaFenetre.h.

Les boîtes de dialogue « saisir une information » peuvent être de quatre types :

  1. saisir un texte :QInputDialog::getText();

  2. saisir un entier :QInputDialog::getInteger();

  3. saisir un nombre décimal :QInputDialog::getDouble();

  4. choisir un élément parmi une liste :QInputDialog::getItem().

Nous nous concentrerons ici sur la saisie de texte mais vous vous rendrez compte que la saisie des autres éléments est relativement proche.

La méthode statiqueQInputDialog::getText()ouvre une boîte de dialogue qui permet à l'utilisateur de saisir un texte.
Son prototype est :

QString QInputDialog::getText ( QWidget * parent, const QString & title, const QString & label, QLineEdit::EchoMode mode = QLineEdit::Normal, const QString & text = QString(), bool * ok = 0, Qt::WindowFlags f = 0 );

Vous pouvez tout d'abord constater que la méthode renvoie un QString, c'est-à-dire une chaîne de caractères de Qt.
Les paramètres signifient, dans l'ordre :

  • parent: pointeur vers la fenêtre parente. Peut être mis à NULLpour ne pas indiquer de fenêtre parente.

  • title: titre de la fenêtre, affiché en haut.

  • label: texte affiché dans la fenêtre.

  • mode: mode d'édition du texte. Permet de dire si on veut que les lettres s'affichent quand on tape, ou si elles doivent être remplacées par des astérisques (pour les mots de passe) ou si aucune lettre ne doit s'afficher. Toutes les options sont dans la documentation. Par défaut, les lettres s'affichent normalement (QLineEdit::Normal).

  • text: texte par défaut dans la zone de saisie.

  • ok: pointeur vers un booléen pour que Qt puisse vous dire si l'utilisateur a cliqué sur OK ou sur Annuler.

  • f: quelques flags (options) permettant d'indiquer si la fenêtre est modale (bloquante) ou pas. Les valeurs possibles sont détaillées par la documentation.

Heureusement, comme vous pouvez le constater en lisant le prototype, certains paramètres possèdent des valeurs par défaut, ce qui les rend facultatifs.

Reprenons notre code de tout à l'heure et cette fois, au lieu d'afficher uneQMessageBox, nous allons afficher une QInputDialoglorsqu'on clique sur le bouton de la fenêtre.

void MaFenetre::ouvrirDialogue()
{
    QString pseudo = QInputDialog::getText(this, "Pseudo", "Quel est votre pseudo ?");
}

En une ligne, je crée un QStringet je lui affecte directement la valeur renvoyée par la méthode getText(). J'aurais aussi bien pu faire la même chose en deux lignes.

La boîte de dialogue devrait ressembler à la figure suivante :

Saisie de texte

On peut aller plus loin et vérifier si le bouton OK a été actionné. Si c'est le cas, on peut alors afficher le pseudo de l'utilisateur dans uneQMessageBox.

void MaFenetre::ouvrirDialogue()
{
    bool ok = false;
    QString pseudo = QInputDialog::getText(this, "Pseudo", "Quel est votre pseudo ?", QLineEdit::Normal, QString(), &ok);
 
    if (ok && !pseudo.isEmpty())
    {
        QMessageBox::information(this, "Pseudo", "Bonjour " + pseudo + ", ça va ?");
    }
    else
    {
        QMessageBox::critical(this, "Pseudo", "Vous n'avez pas voulu donner votre nom… snif.");
    }
}

Ici, on crée un booléen qui reçoit l'information « A-t-on cliqué sur le bouton OK ? ».

Pour pouvoir l'utiliser dans la méthode getText, il faut donner tous les paramètres qui sont avant, même ceux qu'on ne souhaite pourtant pas changer ! C'est un des défauts des paramètres par défaut en C++ : si le paramètre que vous voulez renseigner est tout à la fin (à droite), il faudra alors absolument renseigner tous les paramètres qui sont avant !
J'ai donc envoyé des valeurs par défaut aux paramètres qui étaient avant, à savoir modeettext.

Comme j'ai donné à la méthode un pointeur vers mon booléen, celle-ci va le remplir pour indiquer si oui ou non il y a eu un clic sur le bouton.

Je peux ensuite faire un test, d'où la présence de monif. Je vérifie 2 choses :

  • si on a cliqué sur le bouton OK ;

  • et si le texte n'est pas vide (la méthode isEmptyde QStringsert à cela).

Si un pseudo a été saisi et que l'utilisateur a cliqué sur OK, alors une boîte de dialogue lui souhaite la bienvenue. Sinon, une erreur est affichée.

Le schéma suivante présente ce qui peut se produire :

Schéma des possibilités de réaction du programme getText
Schéma des possibilités de réaction du programme getText

Exercice : essayez d'afficher le pseudo de l'utilisateur quelque part sur la fenêtre mère, par exemple sur le bouton.

Sélectionnez une police

La boîte de dialogue « Sélectionner une police » est une des boîtes de dialogue standard les plus connues. Nul doute que vous l'avez déjà rencontrée dans l'un de vos programmes favoris :

Fenêtre de sélection de police
Fenêtre de sélection de police

La boîte de dialogue de sélection de police est gérée par la classe QFontDialog. Celle-ci propose en gros une seule méthode statique surchargée (il y a plusieurs façons de l'utiliser).

Prenons le prototype le plus compliqué, juste pour la forme :

QFont getFont ( bool * ok, const QFont & initial, QWidget * parent, const QString & caption )

Les paramètres sont normalement assez faciles à comprendre.

On retrouve le pointeur vers un booléen ok, qui permet de savoir si l'utilisateur a cliqué sur OK ou a annulé.
On peut spécifier une police par défaut (initial), il faudra envoyer un objet de type QFont. Voilà justement que la classe QFontréapparaît !
Par ailleurs, la chaîne captioncorrespond au message qui sera affiché en haut de la fenêtre.

Enfin, et surtout, la méthode renvoie un objet de type QFontcorrespondant à la police qui a été choisie.

Testons ! Histoire d'aller un peu plus loin, je propose que la police que nous aurons sélectionnée soit immédiatement appliquée au texte de notre bouton, par l'intermédiaire de la méthode setFont()que nous avons appris à utiliser il y a quelques chapitres.

void MaFenetre::ouvrirDialogue()
{
    bool ok = false;
 
    QFont police = QFontDialog::getFont(&ok, m_boutonDialogue->font(), this, "Choisissez une police");
 
    if (ok)
    {
        m_boutonDialogue->setFont(police);
    }
}

La méthode getFontprend comme police par défaut celle qui est utilisée par notre bouton m_boutonDialogue(rappelez-vous, font()est une méthode accesseur qui renvoie un QFont).
On teste si l'utilisateur a bien validé la fenêtre et, si c'est le cas, on applique au bouton la police qui vient d'être choisie.

C'est l'avantage de travailler avec les classes de Qt : elles sont cohérentes. La méthode getFontrenvoie unQFontet ceQFont, nous pouvons l'envoyer à notre tour à notre bouton pour qu'il change d'apparence.

Le résultat ? Le voici en figure suivante :

Choix de police
Choix de police

Attention : le bouton ne se redimensionne pas tout seul. Vous pouvez de base le rendre plus large si vous voulez, ou bien le redimensionner après le choix de la police.

Sélectionnez une couleur

Dans la même veine que la sélection de police, nous connaissons probablement tous la boîte de dialogue « Sélection de couleur » (figure suivante).

Fenêtre de sélection de couleur

Utilisez la classe QColorDialoget sa méthode statique getColor().

QColor QColorDialog::getColor ( const QColor & initial = Qt::white, QWidget * parent = 0 );

Elle renvoie un objet de type QColor. Vous pouvez préciser une couleur par défaut, en envoyant un objet de type QColorou en utilisant une des constantes prédéfinies, fournies dans la documentation. En l'absence de paramètre, c'est la couleur blanche qui est sélectionnée, comme nous l'indique le prototype.

Si on veut tester le résultat en appliquant la nouvelle couleur au bouton, c'est un petit peu compliqué. En effet, il n'existe pas de méthode setColorpour les widgets mais une méthode setPalettequi sert à indiquer une palette de couleurs. Il faudra vous renseigner dans ce cas sur la classe QPalette.

Le code que je vous propose ci-dessous ouvre une boîte de dialogue de sélection de couleur, puis crée une palette où la couleur du texte correspond à la couleur qu'on vient de sélectionner, et enfin applique cette palette au bouton :

void MaFenetre::ouvrirDialogue()
{
    QColor couleur = QColorDialog::getColor(Qt::white, this);
 
    QPalette palette;
    palette.setColor(QPalette::ButtonText, couleur);
    m_boutonDialogue->setPalette(palette);
}

Je ne vous demande pas ici de comprendre comment fonctionneQPalette, qui est d'ailleurs une classe que je ne détaillerai pas plus dans le cours. À vous de vous renseigner à son sujet si elle vous intéresse.

Le résultat de l'application est présenté en figure suivante :

Sélection d'une couleur
Sélection d'une couleur

Sélection d'un fichier ou d'un dossier

Allez, plus que la sélection de fichiers et de dossiers et on aura fait le tour d'à peu près toutes les boîtes de dialogue usuelles qui existent !

La sélection de fichiers et de dossiers est gérée par la classeQFileDialogqui propose elle aussi des méthodes statiques faciles à utiliser.

Cette section sera divisée en 3 parties :

  • sélection d'un dossier existant ;

  • ouverture d'un fichier ;

  • enregistrement d'un fichier.

Sélection d'un dossier (QFileDialog::getExistingDirectory)

Il suffit d'appeler la méthode statique aussi simplement que cela :

QString dossier = QFileDialog::getExistingDirectory(this);

Elle renvoie unQStringcontenant le chemin complet vers le dossier demandé.
La fenêtre qui s'ouvre devrait ressembler à la figure suivante.

Sélectionner un dossier
Sélectionner un dossier

Ouverture d'un fichier (QFileDialog::getOpenFileName)

La célèbre boîte de dialogue « Ouverture d'un fichier » est gérée pargetOpenFileName().
Sans paramètre particulier, la boîte de dialogue permet d'ouvrir n'importe quel fichier.

Vous pouvez néanmoins créer un filtre (en dernier paramètre) pour afficher par exemple uniquement les images.

Ce code demande d'ouvrir un fichier image. Le chemin vers le fichier est stocké dans unQString, que l'on affiche ensuite via uneQMessageBox:

void MaFenetre::ouvrirDialogue()
{
    QString fichier = QFileDialog::getOpenFileName(this, "Ouvrir un fichier", QString(), "Images (*.png *.gif *.jpg *.jpeg)");
    QMessageBox::information(this, "Fichier", "Vous avez sélectionné :\n" + fichier);
}

Le troisième paramètre degetOpenFileNameest le nom du répertoire par défaut dans lequel l'utilisateur est placé. J'ai laissé la valeur par défaut (QString(), ce qui équivaut à écrire""), donc la boîte de dialogue affiche par défaut le répertoire dans lequel est situé le programme.

Grâce au quatrième paramètre, j'ai choisi de filtrer les fichiers. Seules les images de type PNG, GIF, JPG et JPEG s'afficheront :

Ouvrir un fichier
Ouvrir un fichier

La fenêtre bénéficie de toutes les options que propose votre OS, dont l'affichage des images sous forme de miniatures.
Lorsque vous cliquez sur « Ouvrir », le chemin est enregistré dans unQStringqui s'affiche ensuite dans une boîte de dialogue :

Le fichier sélectionné s'affiche

Enregistrement d'un fichier (QFileDialog::getSaveFileName)

C'est le même principe que la méthode précédente, à la différence près que, pour l'enregistrement, la personne peut cette fois spécifier un nom de fichier qui n'existe pas. Le bouton « Ouvrir » est remplacé par « Enregistrer » :

QString fichier = QFileDialog::getSaveFileName(this, "Enregistrer un fichier", QString(), "Images (*.png *.gif *.jpg *.jpeg)");
Enregistrer un fichier
Enregistrer un fichier

En résumé

  • Qt permet de créer facilement des boîtes de dialogue usuelles : information, question, erreur, police, couleur, etc.

  • La plupart de ces boîtes de dialogue s'ouvrent à l'aide d'une méthode statique.

  • Leur usage est simple, tant qu'on prend bien le soin de lire la documentation pour comprendre comment appeler les fonctions.

Exemple de certificat de réussite
Exemple de certificat de réussite