Accès rapide :
La vidéo
Obtenir la barre de menu de votre fenêtre principale
Ajouter un menu déroulant dans la barre de menu
Ajouter un menu déroulant dans un menu déroulant
Travaux pratiques
L'énoncé
La correction
Cette vidéo vous montre comment constituer une barre de menu en Qt et utilisant les actions étudiées précédemment.
Pour rappel, une fenêtre principale (classe QMainWindow
)
est divisée en plusieurs zones : l'emplacement pour la barre de menu, les emplacements relatifs à vos barres d'outils, la zone centrale et la zone
dédiée à la barre de statuts. Voici un diagramme qui illustre cette division de l'espace de la fenêtre principale.
Comme nous l'avons vu dans le précédent chapitre, la barre de menu est déjà gérée par votre fenêtre. Pour l'obtenir, il vous suffit d'invoquer la méthode
menuBar
. En fait, c'est cette méthode qui réalise l'instanciation
de la barre de menu : si vous ne l'invoquer pas, vous ne visualiserez pas votre barre. Voici un exemple d'acquisition de la barre de menu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import sys from PySide6.QtGui import QIcon from PySide6.QtWidgets import QApplication, QMainWindow class MyWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("Exemple de définition d'une barre de menu Qt") self.setWindowIcon(QIcon("icons/file.png")) self.resize(600, 150) # On récupère la barre de menu de la fenêtre principale. menuBar = self.menuBar() # Vous pouvez maintenant insérer vos actions dans la barre de menu. if __name__ == "__main__": app = QApplication(sys.argv) myWindow = MyWindow() myWindow.show() sys.exit(app.exec()) |
Pour ajouter un menu dans la barre de menu, vous devez utiliser la méthode
addMenu
. Celle-ci accepte une chaîne de caractères : le libellé
affiché en haut du menu déroulant.
Tout comme pour les actions, étudiées dans le chapitre précédent, vous pouvez ajouter un caractère souligné pour permettre
l'accéder au menu à partir du clavier. Ainsi, dans l'exemple suivant, la lettre F
servira à l'ouverture du menu File
(il faudra
appuyer simultanément sur les touches ALT
et F
).
1 2 |
menuBar = self.menuBar()
file = menuBar.addMenu("&File")
|
Une fois le menu en place, vous pouvez y ajouter vos actions. Il est possible de regrouper plusieurs actions dans un même compartiment en rajoutant des séparateurs dans le menu déroulant. Dans l'exemple suivant, j'ai essayé de structurer mon code en plusieurs méthodes afin d'éviter d'avoir un trop gros constructeur.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
import sys from PySide6.QtCore import Slot from PySide6.QtGui import QIcon, QAction from PySide6.QtWidgets import QApplication, QMainWindow class MyWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("Exemple de définition d'une barre de menu Qt") self.setWindowIcon(QIcon("icons/file.png")) self.resize(600, 150) self.createActions() self.createMenuBar() statusBar = self.statusBar() statusBar.showMessage(self.windowTitle()) # Définition du message initial def createActions(self): self.actNew = QAction(QIcon("icons/new.png"), "&New", self) self.actNew.setShortcut("Ctrl+N") self.actNew.setStatusTip("New document") self.actNew.triggered.connect(self.newDocument) self.actOpen = QAction(QIcon("icons/open.png"), "&Open...", self) self.actOpen.setShortcut("Ctrl+O") self.actOpen.setStatusTip("Open file") self.actSave = QAction(QIcon("icons/save.png"), "&Save", self) self.actSave.setShortcut("Ctrl+S") self.actSave.setStatusTip("Save File") self.actExit = QAction(QIcon("icons/exit.png"), "Exit", self) self.actExit.setShortcut("Alt+F4") self.actExit.setStatusTip("Exit") # La méthode close est directement fournie par la classe QMainWindow. self.actExit.triggered.connect(self.close) def createMenuBar(self): menuBar = self.menuBar() file = menuBar.addMenu("&File") file.addAction(self.actNew) file.addSeparator() file.addAction(self.actOpen) file.addAction(self.actSave) file.addSeparator() file.addAction(self.actExit) @Slot() def newDocument(self): print("New document is requested") if __name__ == "__main__": app = QApplication(sys.argv) myWindow = MyWindow() myWindow.show() sys.exit(app.exec()) |
createToolBars
...).
Et voici le résultat obtenu si vous déroulez le menu File
.
...
.
C'est une convention assez classique : si votre action ouvre une nouvelle boîte de dialogue, alors on rajoute ces trois caractères.
Amusez-vous à ouvrir le menu File de PyCharm et vous verrez qu'eux aussi respectent cette convention.
Un menu déroulant peut proposer un (ou plusieurs) sous-menu(s). Pour ce faire, il faut invoquer la méthode addMenu
sur le menu parent.
Il n'y a pas de limite de profondeur, si ce n'est que votre interface doit rester ergonomique.
Voici comment ajouter un sous-menu à votre menu File
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
def createMenuBar(self): menuBar = self.menuBar() actFile1 = QAction(QIcon("icons/new.png"), "File-1.txt", self) actFile1.setStatusTip(actFile1.text()) actFile2 = QAction(QIcon("icons/new.png"), "File-2.txt", self) actFile2.setStatusTip(actFile2.text()) actFile3 = QAction(QIcon("icons/new.png"), "File-3.txt", self) actFile3.setStatusTip(actFile3.text()) file = menuBar.addMenu("&File") file.addAction(self.actNew) file.addSeparator() file.addAction(self.actOpen) file.addAction(self.actSave) file.addSeparator() recentFiles = file.addMenu("Recent files") recentFiles.addAction(actFile1) recentFiles.addAction(actFile2) recentFiles.addAction(actFile3) file.addSeparator() file.addAction(self.actExit) |
Et voici le rendu visuel produit par cet exemple.
En repartant de l'exemple proposé ci-dessus, veuillez rajouter un menu « Edit » (avec les éléments « Undo », « Redo », « Copy », « Cut » et « Paste ») ainsi qu'un autre menu « Help » (avec un élément « About... »).
Essayez de faire l'exercice sans regarder directement la correction ci-dessous. ;-)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
import sys from PySide6.QtCore import Slot from PySide6.QtGui import QIcon, QAction from PySide6.QtWidgets import QApplication, QMainWindow, QFileDialog, QMessageBox class MyWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("Exemple de définition d'une barre de menu Qt") self.setWindowIcon(QIcon("icons/file.png")) self.resize(600, 150) self.createActions() self.createMenuBar() statusBar = self.statusBar() statusBar.showMessage(self.windowTitle()) # Définition du message initial def createActions(self): self.actNew = QAction(QIcon("icons/new.png"), "&New", self) self.actNew.setShortcut("Ctrl+N") self.actNew.setStatusTip("New document") self.actNew.triggered.connect(self.newDocument) self.actOpen = QAction(QIcon("icons/open.png"), "&Open...", self) self.actOpen.setShortcut("Ctrl+O") self.actOpen.setStatusTip("Open file") self.actOpen.triggered.connect(self.openDocument) self.actSave = QAction(QIcon("icons/save.png"), "&Save", self) self.actSave.setShortcut("Ctrl+S") self.actSave.setStatusTip("Save File") self.actExit = QAction(QIcon("icons/exit.png"), "Exit", self) self.actExit.setShortcut("Alt+F4") self.actExit.setStatusTip("Exit") # La méthode close est directement fournie par la classe QMainWindow. self.actExit.triggered.connect(self.close) self.actUndo = QAction(QIcon("icons/undo.png"), "&Undo", self) self.actUndo.setShortcut("Ctrl+Z") self.actUndo.setStatusTip("Undo") self.actRedo = QAction(QIcon("icons/redo.png"), "&Redo", self) self.actRedo.setShortcut("Ctrl+Y") self.actRedo.setStatusTip("Redo") self.actCopy = QAction(QIcon("icons/copy.png"), "&Copy", self) self.actCopy.setShortcut("Ctrl+C") self.actCopy.setStatusTip("Copy") self.actCut = QAction(QIcon("icons/cut.png"), "Cu&t", self) self.actCut.setShortcut("Ctrl+X") self.actCut.setStatusTip("Cut") self.actPaste = QAction(QIcon("icons/paste.png"), "&Paste", self) self.actPaste.setShortcut("Ctrl+V") self.actPaste.setStatusTip("Paste") self.actAbout = QAction(QIcon("icons/about.png"), "About...", self) self.actAbout.setStatusTip("About...") self.actAbout.triggered.connect(self.about) def createMenuBar(self): menuBar = self.menuBar() actFile1 = QAction(QIcon("icons/new.png"), "File-1.txt", self) actFile1.setStatusTip(actFile1.text()) actFile2 = QAction(QIcon("icons/new.png"), "File-2.txt", self) actFile2.setStatusTip(actFile2.text()) actFile3 = QAction(QIcon("icons/new.png"), "File-3.txt", self) actFile3.setStatusTip(actFile3.text()) file = menuBar.addMenu("&File") file.addAction(self.actNew) file.addSeparator() file.addAction(self.actOpen) file.addAction(self.actSave) file.addSeparator() recentFiles = file.addMenu("Recent files") recentFiles.addAction(actFile1) recentFiles.addAction(actFile2) recentFiles.addAction(actFile3) file.addSeparator() file.addAction(self.actExit) edit = menuBar.addMenu("&Edit") edit.addAction(self.actUndo) edit.addAction(self.actRedo) edit.addSeparator() edit.addAction(self.actCopy) edit.addAction(self.actCut) edit.addAction(self.actPaste) helpMenu = menuBar.addMenu("&Help") helpMenu.addAction(self.actAbout) @Slot() def newDocument(self): print("New document is requested") @Slot() def openDocument(self): filename, selectedFilter = QFileDialog.getOpenFileName(self, "Open file", ".") print(filename, selectedFilter) @Slot() def about(self): QMessageBox.information(self, self.windowTitle(), "MenuBar Sample V1.0") if __name__ == "__main__": app = QApplication(sys.argv) myWindow = MyWindow() myWindow.show() sys.exit(app.exec()) |
Et voici le résultat produit par cet exemple.
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :