Participer au site avec un Tip
Rechercher
 

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 :

Thèmes graphiques et feuilles de styles QSS

Liens avec les technologies Web Définition d'actions Qt


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

La vidéo

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é.


Thèmes graphiques et feuilles de styles QSS.

La fenêtre de test que nous allons étudier

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.

Le thème Qt Fusion (il est proposé directement par Qt)
selon le système d'exploitation utilisé, le thème par défaut n'est pas le même.
de nombreux widgets non encore étudiés sont proposés dans cet exemple. Ne vous inquiétez pas, nous allons y revenir en détails dans les prochains chapitres. Néanmoins, si vous souhaitez vous aussi tester les différents thèmes proposés, vous pouvez dés à présent en retrouver le code à la fin de ce document.

Les thèmes proposés de base par Qt/PySide6

Le thème Fusion

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.

Le thème Qt Fusion (il est proposé directement par Qt).

Le thème Windows

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.

Le thème Qt Windows (inspiré de Windows XP).

Le thème WindowsVista

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.

Le thème Qt WindowsVista (il n'est pas proposé sur Linux/Unix).
ce thème n'est actuellement pas disponible sous système d'exploitation Linux/Unix.

Quelques feuilles de styles QSS téléchargeable sur Internet

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

QSS est un langage dérivé de CSS, spécifique à la décoration/stylisation de vos applications Qt. Pour de plus amples informations sur QSS/CSS, je vous renvoie vers le chapitre précédent : « Liens avec les technologies Web (HTML/CSS) ».

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 (QSS-Stock)

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 Adaptic proposée par QSS-Stock.

La feuille de style Combinear (QSS-Stock)

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 Combinear proposée par QSS-Stock.

La feuille de style Darkeum (QSS-Stock)

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 Darkeum proposée par QSS-Stock.

La feuille de style Diffnes (QSS-Stock)

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 Diffnes proposée par QSS-Stock.

La feuille de style EasyCode (QSS-Stock)

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 EasyCode proposée par QSS-Stock.

La feuille de style Fibers (QSS-Stock)

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 Fibers proposée par QSS-Stock.

La feuille de style Integrid (QSS-Stock)

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 Integrid proposée par QSS-Stock.

La feuille de style Irrorater (QSS-Stock)

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 Irrorater proposée par QSS-Stock.

La feuille de style MailSy (QSS-Stock)

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 MailSy proposée par QSS-Stock.

La feuille de style VisualScript (QSS-Stock)

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.

La feuille de style VisualScript proposée par QSS-Stock.

Le code de la fenêtre proposée dans ce chapitre

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())
Le code de la fenêtre utilisée dans ce chapitre
je vous laisse, bien entendu, libre de choisir les icônes que vous souhaitez pour vos actions. Néanmoins, si vous n'avez pas encore d'icônes et que vous souhaitez rapidement faire quelques premiers tests, vous pouvez télécharger le jeu d'icônes que j'utilise pour mes exemples.


Liens avec les technologies Web Définition d'actions Qt