Accès rapide :
La vidéo
La fenêtre de test que nous allons étudier
Les thèmes proposés de base par Qt/PySide6
Le thème Fusion
Le thème Windows
Le thème WindowsVista
Quelques feuilles de styles QSS téléchargeable sur Internet
La feuille de style Adaptic (QSS-Stock)
La feuille de style Combinear (QSS-Stock)
La feuille de style Darkeum (QSS-Stock)
La feuille de style Diffnes (QSS-Stock)
La feuille de style EasyCode (QSS-Stock)
La feuille de style Fibers (QSS-Stock)
La feuille de style Integrid (QSS-Stock)
La feuille de style Irrorater (QSS-Stock)
La feuille de style MailSy (QSS-Stock)
La feuille de style VisualScript (QSS-Stock)
Le code de la fenêtre proposée dans ce chapitre
Cette vidéo vous montre comment changer le thème graphique de votre application Qt. Un site proposant de nombreux thèmes applicables à votre application Qt vous y est aussi présenté.
Voici la fenêtre graphique que nous allons considérer dans ce chapitre : comme vous pouvez le constater, le résultat est déjà, esthétiquement parlant, très intéressant.
Sous Linux/Unix, c'est le thème Fusion qui est appliqué par défaut (c'est le cas de la capture d'écran ci-dessus).
Sous Windows, c'est le thème WindowsVista qui est appliqué par défaut.
Pour démarrer votre programme avec le thème Fusion, proposé par Qt, veuillez procéder ainsi :
$> python StyleDemo.py -style Fusion
Et voici le résultat obtenu.
Pour démarrer votre programme avec le thème Windows, proposé par Qt, veuillez procéder ainsi :
$> python StyleDemo.py -style Windows
Et voici le résultat obtenu.
Pour démarrer votre programme avec le thème WindowsVista, proposé par Qt, veuillez procéder ainsi :
$> python StyleDemo.py -style WindowsVista
Et voici le résultat obtenu.
Il existe de très nombreux sites Web proposant des feuilles de styles QSS pour vos applications Qt. Vous en retrouverez déjà quelques-unes sur le site officiel de Qt : https://wiki.qt.io/Gallery_of_Qt_CSS_Based_Styles
Mais, personnellement, je porterais mon attention sur le site QSS-Stock : https://qss-stock.devsecstudio.com/index.php. Il propose un grand nombre de feuilles de style très sympathiques que vous pouvez appliquer à vos applications Qt. Parmi l'ensemble des thèmes proposés, j'en ai retenu quelques-uns (il y en a pour tous les goûts).
La feuille de style Adaptic est disponible à l'adresse suivante : https://qss-stock.devsecstudio.com/templates/components/components1/adaptic/Adaptic.rar
Pour démarrer votre programme avec la feuille de style Adaptic, proposée par QSS-Stock, veuillez procéder ainsi :
$> python StyleDemo.py -stylesheet Adaptic.qss
Et voici le résultat obtenu.
La feuille de style Combinear est disponible à l'adresse suivante : https://qss-stock.devsecstudio.com/templates/components/components2/combinear/Combinear.rar
Pour démarrer votre programme avec la feuille de style Combinear, proposée par QSS-Stock, veuillez procéder ainsi :
$> python StyleDemo.py -stylesheet Combinear.qss
Et voici le résultat obtenu.
La feuille de style Darkeum est disponible à l'adresse suivante : https://qss-stock.devsecstudio.com/templates/components/components1/darkeum/Darkeum.rar
Pour démarrer votre programme avec la feuille de style Darkeum, proposée par QSS-Stock, veuillez procéder ainsi :
$> python StyleDemo.py -stylesheet Darkeum.qss
Et voici le résultat obtenu.
La feuille de style Diffnes est disponible à l'adresse suivante : https://qss-stock.devsecstudio.com/templates/components/components3/diffnes/Diffnes.rar
Pour démarrer votre programme avec la feuille de style Diffnes, proposée par QSS-Stock, veuillez procéder ainsi :
$> python StyleDemo.py -stylesheet Diffnes.qss
Et voici le résultat obtenu.
La feuille de style EasyCode est disponible à l'adresse suivante : https://qss-stock.devsecstudio.com/templates/scientific/programmingeditor/easycode/EasyCode.rar
Pour démarrer votre programme avec la feuille de style EasyCode, proposée par QSS-Stock, veuillez procéder ainsi :
$> python StyleDemo.py -stylesheet EasyCode.qss
Et voici le résultat obtenu.
La feuille de style Fibers est disponible à l'adresse suivante : https://qss-stock.devsecstudio.com/templates/components/components3/fibers/Fibers.rar
Pour démarrer votre programme avec la feuille de style Fibers, proposée par QSS-Stock, veuillez procéder ainsi :
$> python StyleDemo.py -stylesheet Fibers.qss
Et voici le résultat obtenu.
La feuille de style Integrid est disponible à l'adresse suivante : https://qss-stock.devsecstudio.com/templates/components/components2/integrid/Integrid.rar
Pour démarrer votre programme avec la feuille de style Integrid, proposée par QSS-Stock, veuillez procéder ainsi :
$> python StyleDemo.py -stylesheet Integrid.qss
Et voici le résultat obtenu.
La feuille de style Irrorater est disponible à l'adresse suivante : https://qss-stock.devsecstudio.com/templates/components/components1/irrorater/Irrorater.rar
Pour démarrer votre programme avec la feuille de style Irrorater, proposée par QSS-Stock, veuillez procéder ainsi :
$> python StyleDemo.py -stylesheet Irrorater.qss
Et voici le résultat obtenu.
La feuille de style MailSy est disponible à l'adresse suivante : https://qss-stock.devsecstudio.com/templates/network/webmail/mailsy/MailSy.rar
Pour démarrer votre programme avec la feuille de style MailSy, proposée par QSS-Stock, veuillez procéder ainsi :
$> python StyleDemo.py -stylesheet MailSy.qss
Et voici le résultat obtenu.
La feuille de style VisualScript est disponible à l'adresse suivante : https://qss-stock.devsecstudio.com/templates/scientific/programmingeditor/visualscript/VisualScript.rar
Pour démarrer votre programme avec la feuille de style VisualScript, proposée par QSS-Stock, veuillez procéder ainsi :
$> python StyleDemo.py -stylesheet VisualScript.qss
Et voici le résultat obtenu.
Et voici le code Python de la fenêtre graphique présentée dans ce document. Si certains point du programme vous paraissent encore un peu obscurs, rien de grave, nous allons y revenir dans les prochains chapitres.
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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
import sys from PySide6.QtCore import Slot, QDir, QModelIndex, QPersistentModelIndex from PySide6.QtGui import QIcon, QAction, QCloseEvent, Qt from PySide6.QtWidgets import QApplication, QMainWindow, QMessageBox, QFileDialog, QComboBox, QCheckBox, QLabel, \ QProgressBar, QSplitter, QTabWidget, QTreeView, QTextEdit, QTableView, QFileSystemModel, QWidget, QGroupBox, \ QGridLayout, QRadioButton, QVBoxLayout, QScrollBar, QSpinBox, QSlider, QPushButton, QLineEdit, QLCDNumber class MyWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("Test styles with PySide6/Qt") self.setWindowIcon(QIcon("icons/yes.png")) self.resize(1024, 500) self.createBars() self.createCentralArea() def createCentralArea(self): # Un QSplitter permet de diviser l'espace en sous-zones. # Un séparateur permet de contrôler l'espace alloué à chaque zone. splitter = QSplitter(Qt.Horizontal) # Un QTreeView permet d'afficher une arborescence. # Grâce au QFileSystemModel, on connecte le tree sur le disque dur. treeModel = QFileSystemModel() treeModel.setRootPath(QDir.currentPath()) treeView = QTreeView() treeView.setModel(treeModel) treeView.expandToDepth(0) # Ouverture du premier niveau # Un QTabWidget permet de définir des onglets tabWidget = QTabWidget(splitter) tabWidget.setTabPosition(QTabWidget.South) tabWidget.setMinimumWidth(300) tabWidget.addTab(treeView, "File System") tabWidget.addTab(QTreeView(), "Database") tabWidget.addTab(QTreeView(), "Help") # Un autre splitter pour séparer l'espace de droite du splitter principal # en deux sous-zones affichées l'une sous l'autre (Qt.Vertical). verticalSplitter = QSplitter(Qt.Vertical, splitter) editor = QTextEdit(verticalSplitter) self.fillEditor(editor) propertyPanel = QWidget(verticalSplitter) gridLayout = QGridLayout(propertyPanel) gridLayout.addWidget(self.createFirstGroupBox(), 0, 0) group2 = QGroupBox("Second group") gridLayout.addWidget(self.createSecondGroupBox(), 0, 1) group3 = QGroupBox("Third group") gridLayout.addWidget(self.createThirdGroupBox(), 0, 2) # On définit le splitter principal comme étant le "Central Widget". self.setCentralWidget(splitter) def fillEditor(self, editor): # On charge le contenu du fichier dans l'éditeur with open("StyleDemo.py", "r") as file: content = "".join(file.readlines()) editor.setText(content) def createFirstGroupBox(self): # On définit un premier groupe de cases à cocher (exclusives). group1 = QGroupBox("First group") vBox = QVBoxLayout() vBox.addWidget(QRadioButton("Exclusive choice 1", checked=True)) vBox.addWidget(QRadioButton("Exclusive choice 2")) vBox.addWidget(QRadioButton("Exclusive choice 3")) vBox.addStretch(1) group1.setLayout(vBox) return group1 def createSecondGroupBox(self): # On définit un second groupe de cases à cocher (non exclusives). group2 = QGroupBox("Second group") vBox = QVBoxLayout() vBox.addWidget(QCheckBox("Choice 1", checked=True)) vBox.addWidget(QCheckBox("Choice 2", checked=True)) vBox.addWidget(QCheckBox("Choice 3")) vBox.addStretch(1) group2.setLayout(vBox) return group2 def createThirdGroupBox(self): # On définit un dernier groupe de widgets. group3 = QGroupBox("Third group") vBox = QVBoxLayout() vBox.addWidget(QSpinBox(value=50)) vBox.addWidget(QSlider(Qt.Horizontal, value=50)) vBox.addWidget(QPushButton("Click me")) vBox.addWidget(QLineEdit("Edit me")) vBox.addWidget(QLCDNumber(value=50)) vBox.addStretch(1) group3.setLayout(vBox) return group3 def createBars(self): # Définitions des actions : elles seront associées à la barre # de menu et aux différentes barres d'outils. actNew = QAction(QIcon("icons/new.png"), "&New", self) actNew.setShortcut("Ctrl+N") actNew.setStatusTip("New document") actNew.triggered.connect(self.new) actOpen = QAction(QIcon("icons/open.png"), "&Open...", self) actOpen.setShortcut("Ctrl+O") actOpen.setStatusTip("Open file") actOpen.triggered.connect(self.open) actSave = QAction(QIcon("icons/save.png"), "&Save", self) actSave.setShortcut("Ctrl+S") actSave.setStatusTip("Save File") actExit = QAction(QIcon("icons/exit.png"), "Exit", self) actExit.setShortcut("Alt+F4") actExit.setStatusTip("Exit") actExit.triggered.connect(self.close) actUndo = QAction(QIcon("icons/undo.png"), "&Undo", self) actUndo.setShortcut("Ctrl+Z") actUndo.setStatusTip("Undo") actRedo = QAction(QIcon("icons/redo.png"), "&Redo", self) actRedo.setShortcut("Ctrl+Y") actRedo.setStatusTip("Redo") actCopy = QAction(QIcon("icons/copy.png"), "&Copy", self) actCopy.setShortcut("Ctrl+C") actCopy.setStatusTip("Copy") actCut = QAction(QIcon("icons/cut.png"), "Cu&t", self) actCut.setShortcut("Ctrl+X") actCut.setStatusTip("Cut") actPaste = QAction(QIcon("icons/paste.png"), "&Paste", self) actPaste.setShortcut("Ctrl+V") actPaste.setStatusTip("Paste") actAbout = QAction(QIcon("icons/about.png"), "About...", self) actAbout.setStatusTip("About...") # Définition de la barre de menu menuBar = self.menuBar() file = menuBar.addMenu("&File") file.addAction(actNew) file.addSeparator() file.addAction(actOpen) file.addAction(actSave) file.addSeparator() file.addAction(actExit) edit = menuBar.addMenu("&Edit") edit.addAction(actUndo) edit.addAction(actRedo) edit.addSeparator() edit.addAction(actCopy) edit.addAction(actCut) edit.addAction(actPaste) help = menuBar.addMenu("&Help") help.addAction(actAbout) # Définition de trois barres d'outils toolbar = self.addToolBar("Standard ToolBar") toolbar.addAction(actNew) toolbar.addSeparator() toolbar.addAction(actOpen) toolbar.addAction(actSave) toolbar.addSeparator() toolbar.addAction(actExit) toolbar2 = self.addToolBar("Edit ToolBar") toolbar2.addAction(actUndo) toolbar2.addAction(actRedo) toolbar2.addSeparator() toolbar2.addAction(actCopy) toolbar2.addAction(actCut) toolbar2.addAction(actPaste) toolbar3 = self.addToolBar("Test ToolBar") comboBox = QComboBox(self) comboBox.addItems(["First item", "Second item", "Third item"]) toolbar3.addWidget(comboBox) toolbar3.addSeparator() toolbar3.addWidget(QCheckBox("Check me", self)) # Définition de la barre de statuts statusBar = self.statusBar() statusBar.showMessage("Theme/Stylesheet usage") progress = QProgressBar() progress.setMaximumHeight(18) progress.setValue(50) label = QLabel("Text position: 31,25") statusBar.addPermanentWidget(progress) statusBar.addPermanentWidget(label) def closeEvent(self, event: QCloseEvent) -> None: reply = QMessageBox.question(self, self.windowTitle(), "Are you sure to quit?", QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() else: event.ignore() @Slot() def new(self): print("New document requested") @Slot() def open(self): filename, selectedFilter = QFileDialog.getOpenFileName(self, "Open file", ".") print(filename, selectedFilter) if __name__ == "__main__": app = QApplication(sys.argv) myWindow = MyWindow() myWindow.show() sys.exit(app.exec()) |
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 :