La QMainWindow peut afficher une barre de menus, comme par exemple : Fichier, Edition, Affichage, Aide...
Comment fait-on pour les créer ?
Créer un menu pour la fenêtre principale
La barre de menus est accessible depuis la méthode menuBar(). Cette méthode renvoie un pointeur sur un QMenuBar, qui vous propose une méthode addMenu(). Cette méthode renvoie un pointeur sur le QMenu créé.
Puisqu'un petit code vaut tous les discours du monde, voici comment faire :
Code : C++1
2
3
4
5
6
7
8 | #include "FenPrincipale.h"
FenPrincipale::FenPrincipale()
{
QMenu *menuFichier = menuBar()->addMenu("&Fichier");
QMenu *menuEdition = menuBar()->addMenu("&Edition");
QMenu *menuAffichage = menuBar()->addMenu("&Affichage");
}
|
Avec ça, nous avons créé 3 menus dont nous gardons les pointeurs (menuFichier, menuEdition, menuAffichage). Vous noterez qu'on utilise ici aussi le symbole & pour définir des raccourcis clavier (les lettres F, E et A seront donc des raccourcis vers leurs menus respectifs).
Nous avons maintenant 3 menus sur notre fenêtre :
Mais... ces menus n'affichent rien ! En effet, ils ne contiennent pour le moment aucun élément.
Création d'actions pour les menus
Un
élément de menu est représenté par une
action. C'est la classe
QAction qui gère ça.
Pourquoi avoir créé une classe QAction au lieu de... je sais pas moi... QSubMenu pour dire "sous-menu" ?
En fait, les QAction sont des éléments de menu génériques. Ils peuvent être utilisés à la fois pour les menus et pour la barre d'outils.
Par exemple, imaginons l'élément "Nouveau" qui permet de créer un nouveau document. On peut en général y accéder depuis 2 endroits différents :
- Le menu Fichier / Nouveau.
- Le bouton de la barre d'outils "Nouveau", généralement représenté par une icône de document vide.
Une seule QAction peut servir à définir ces 2 éléments à la fois.
Les développeurs de Qt se sont en effet rendus compte que les actions des menus étaient souvent dupliquées dans la barre d'outils, d'où la création de la classe QAction que nous réutiliserons lorsque nous créerons la barre d'outils.
Pour créer une action vous avez 2 possibilités :
- Soit vous la créez d'abord, puis vous créez l'élément de menu qui correspond.
- Soit vous créez l'élément de menu directement, et celui-ci vous renvoie un pointeur vers la QAction créée automatiquement.
Nous allons tester ces 2 possibilités.
Créer une QAction, puis créer l'élément de menu
Nous allons tout d'abord créer une QAction, puis nous l'ajouterons au menu "Fichier" :
Code : C++ 1
2
3
4
5
6
7
8
9
10
11
12
13
14 | #include "FenPrincipale.h"
FenPrincipale::FenPrincipale()
{
QMenu *menuFichier = menuBar()->addMenu("&Fichier");
QAction *actionQuitter = new QAction("&Quitter", this);
menuFichier->addAction(actionQuitter);
QMenu *menuEdition = menuBar()->addMenu("&Edition");
QMenu *menuAffichage = menuBar()->addMenu("&Affichage");
}
|
Dans l'exemple de code ci-dessus, nous créons d'abord une QAction correspondant à l'action "Quitter". Nous définissons en second paramètre de son constructeur un pointeur sur la fenêtre principale (this), qui servira de parent à l'action.
Puis, nous ajoutons l'action au menu "Fichier".
Résultat, l'élément de menu est créé :
Créer l'élément de menu et récupérer la QAction
Il y a une autre façon de faire.
Parfois, vous trouverez que créer une QAction avant de générer l'élément de menu est un peu lourd. Dans ce cas, vous pouvez passer par une des versions surchargées de la méthode addAction :
Code : C++ 1
2
3
4
5
6
7
8
9
10
11
12
13 | #include "FenPrincipale.h"
FenPrincipale::FenPrincipale()
{
QMenu *menuFichier = menuBar()->addMenu("&Fichier");
QAction *actionQuitter = menuFichier->addAction("&Quitter");
QMenu *menuEdition = menuBar()->addMenu("&Edition");
QMenu *menuAffichage = menuBar()->addMenu("&Affichage");
connect(actionQuitter, SIGNAL(triggered()), qApp, SLOT(quit()));
}
|
Le résultat est strictement le même :
Les sous-menus
Les sous-menus sont gérés par la classe
QMenu.
Imaginons que nous voulions créer un sous-menu "Fichiers récents" au menu "Fichier". Ce sous-menu affichera une liste de fichiers récemment ouverts par le programme (des fichiers bidons pour cet exemple).
Au lieu d'appeler addAction() de la QMenuBar, appelez cette fois addMenu() qui renvoie un pointeur vers un QMenu :
Code : C++1
2
3
4 | QMenu *fichiersRecents = menuFichier->addMenu("Fichiers &récents");
fichiersRecents->addAction("Fichier bidon 1.txt");
fichiersRecents->addAction("Fichier bidon 2.txt");
fichiersRecents->addAction("Fichier bidon 3.txt");
|
Vous voyez que j'ajoute ensuite de nouvelles actions pour peupler le sous-menu "Fichiers récents". Résultat :
Je n'ai pas récupéré de pointeur vers les QAction créées à chaque fois. J'aurais dû le faire si je voulais ensuite connecter les signaux des actions à des slots, mais je ne l'ai pas fait ici pour simplifier le code.
Vous pouvez créer des menus contextuels personnalisés de la même façon, avec des QMenu. Un menu contextuel est un menu qui s'affiche lorsqu'on fait un clic droit sur un widget. C'est un petit peu plus complexe. Je vous laisse lire la doc de QWidget à propos des menus contextuels pour savoir comment faire ça si vous en avez besoin.
Manipulations plus avancées des QAction
Une QAction est au minimum constituée d'un texte descriptif. Mais ce serait dommage de la limiter à ça.
Voyons un peu ce qu'on peut faire avec les QAction...
Connecter les signaux et les slots
Le premier rôle d'une QAction est de générer des signaux, que l'on aura connectés à des slots.
La QAction propose plusieurs signaux intéressants. Le plus utilisé d'entre eux est triggered() qui indique que l'action a été choisie par l'utilisateur.
On peut connecter notre action "Quitter" au slot quit() de l'application :
Code : C++1 | connect(actionQuitter, SIGNAL(triggered()), qApp, SLOT(quit()));
|
Désormais, un clic sur "Fichier / Quitter" fermera l'application.
Vous avez aussi un évènement hovered() qui s'active lorsqu'on passe la souris sur l'action. A tester !
Ajouter un raccourci
On peut définir un raccourci clavier pour l'action. On passe pour cela par la méthode addShortcut().
Cette méthode peut être utilisée de plusieurs manières différentes. La technique la plus simple est de lui envoyer une
QKeySequence représentant le raccourci clavier :
Code : C++1 | actionQuitter->setShortcut(QKeySequence("Ctrl+Q"));
|
Voilà, il suffit d'écrire dans le constructeur de la QKeySequence le raccourci approprié, Qt se chargera de comprendre le raccourci tout seul.
Vous pouvez faire le raccourci clavier Ctrl + Q n'importe où dans la fenêtre maintenant, cela activera l'action "Quitter" !
Sachez que QKeySequence accepte d'autres syntaxes :
Code : C++1 | actionQuitter->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
|
... créera le même raccourci "Ctrl + Q", sauf que cette fois nous sommes passés par des symboles pour le définir.
Vous pouvez aussi utiliser une séquence prédéfinie, qui s'adapte en fonction des habitudes de l'OS.
Par exemple, la séquence prédéfinie QKeySequence::HelpContents est faite pour représenter un raccourci clavier qui amène à l'aide.
Code : C++1 | actionQuitter->setShortcut(QKeySequence(QKeySequence::HelpContents));
|
Sous Windows, ce sera la touche F1, sous Mac OS X, ce sera le raccourci "Ctrl + ?".
Pour avoir la liste des séquences prédéfinies, c'est dans la doc.
Ajouter une icône
Chaque action peut avoir une icône.
Lorsque l'action est associée à un menu, l'icône est affichée à gauche de l'élément de menu. Mais, souvenez-vous, une action peut aussi être associée à une barre d'outils comme on le verra plus tard. L'icône peut donc aussi être réutilisée dans la barre d'outils.
Pour ajouter une icône, appelez setIcon() et envoyez-lui un QIcon :
Code : C++1 | actionQuitter->setIcon(QIcon("quitter.png"));
|
Résultat :
Pouvoir cocher une action
Lorsqu'une action peut avoir 2 états (activée, désactivée), vous pouvez la rendre "cochable" grâce à setCheckable().
Imaginons par exemple le menu Edition / Gras :
Code : C++1 | actionGras->setCheckable(true);
|
Le menu a maintenant 2 états et peut être précédé d'une case à cocher :
On vérifiera dans le code si l'action est cochée avec isChecked().
Lorsque l'action est utilisée sur une barre d'outils, le bouton reste enfoncé lorsque l'action est "cochée". C'est ce que vous avez l'habitude de voir dans un traitement de texte par exemple (cf image ci-contre

).
Ah, puisqu'on parle de barre d'outils, il serait temps d'apprendre à en créer une !