IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
FAQ Qt FAQ Qt Creator FAQ PyQt & PySide

FAQ Qt

FAQ QtConsultez toutes les FAQ

Nombre d'auteurs : 26, nombre de questions : 298, dernière mise à jour : 15 juin 2021 

 
OuvrirSommaireModulesQt GUI et Qt WidgetsGénéralitésStyle

Qt permet diverses actions pour jouer avec la transparence d'une fenêtre.

  • Masque : à partir d'une image binaire (QBitmap), il est possible de spécifier quelle partie est visible ou non sur la fenêtre. Cette méthode s'applique à tous les éléments d'une fenêtre top-level. Par exemple la partie d'un bouton qui se trouve dans une zone transparente ne sera pas dessinée. Pour utiliser un masque il faut créer une QBitmap et utiliser la fonction setMask (définie par QWidget) sur le widget parent. Sur certains OS comme Windows XP, il est obligatoire d'enlever la décoration avec le flag Qt::FramelessWindowHint.
  • Opacité : permet de rendre translucide toute une fenêtre. Pour cela il faut utiliser la méthode setWindowOpacity() (définie par QWidget) sur le widget parent. Cette méthode prend en paramètre une valeur réelle entre 0 (transparent) et 1 (opaque).
  • Transparence : depuis la version 4.5, il est possible de spécifier que le fond du widget parent est transparent. Il est ainsi possible de jouer avec la transparence des différents éléments et QPainter pour créer une fenêtre translucide. Contrairement aux deux autres méthodes, ceci ne s'applique qu'au background de la fenêtre parente et les éléments enfants ne sont pas modifiés. Pour utiliser cette option, il faut activer l'attribut Qt::WA_TranslucentBackground sur le widget parent : setAttribute(Qt::WA_TranslucentBackground, true);. Sur certains OS comme Windows XP, il est obligatoire d'enlever la décoration avec le flag Qt::FramelessWindowHint.

Remarque : ces trois méthodes peuvent être utilisées en même temps.

Exemple des différentes possibilités
Cacher/Afficher le codeSélectionnez
Mis à jour le 7 mai 2012  par Yan Verdavaine

Par défaut, Qt utilise le style natif du système d'exploitation. Si vous voulez modifier le style, vous pouvez le faire au niveau de chaque widget à l'aide de QWidget::setStyle() ou au niveau de l'application complète avec QApplication::setStyle().

Voici, par exemple, comment utiliser le style Plastique pour toute l'application.

 
Sélectionnez
QApplication::setStyle(new QPlastiqueStyle);

Remarque : il est possible de créer un style par son nom avec QStyleFactory::create() ou la fonction statique QApplication::setStyle().

Créer un style complet est généralement une tâche difficile. Heureusement, Qt fournit un mécanisme simple pour personnaliser les styles : les CSS (Cascading Style Sheets). Avec CSS pour Qt, il est possible de personnaliser le design d'une application à l'aide d'une syntaxe simple dérivée du CSS. Cela peut se faire au niveau de designer, ou comme pour les styles classiques, au niveau des widgets ou de l'application.

Une feuille CSS de Qt
Cacher/Afficher le codeSélectionnez
Mis à jour le 7 juillet 2009  par Matthieu Brucher, Benjamin Poulain

Lien : Exemple de création et d'utilisation de style
Lien : Comment connaître les styles disponibles ?

Les styles disponibles dépendent de la plateforme et des extensions. La classe QStyleFactory permet de lever toute ambiguïté en fournissant la liste des styles disponibles à l'exécution. La méthode statique QStyleFactory::keys retourne une liste de noms de style qu'il est possible de charger. À partir des noms de cette liste, il est possible de charger les styles avec la méthode statique QStyleFactory::create.

En général, il est déconseillé de changer de style, car l'application perd son intégration avec le reste du système.

Mis à jour le 7 mai 2012  par Benjamin Poulain

Il existe trois méthodes pour définir l'image de fond d'un widget. Vous pouvez utiliser un QPixmap dans lequel vous initialisez avec l'image de fond souhaitée. Alternativement, vous pouvez définir une nouvelle QPalette, y adjoindre une QBrush qui contient l'image de fond. Finalement, vous pouvez utiliser les feuilles de style. Voici la manière de les utiliser.

 
Sélectionnez
QLabel label;
QPixmap pixmap;

pixmap.load("image.jpg");
label->setPixmap(pixmap);
 
Sélectionnez
QWidget widget;
QPalette palette;

palette.setBrush(this->backgroundRole(), QBrush(QImage("image.jpg")));
this->setPalette(palette);
 
Sélectionnez
QWidget widget;
QString stylesheet("QWidget{ background-image: url(image.jpg); }");

widget.setStyleSheet(stylesheet);

Ces solutions peuvent être utilisées sur tous types de widgets : un bouton, un menu, une fenêtre… Elles ne mettront qu'une image en arrière-plan, elles n'inséreront pas une image dans le widget (comme le bouclier de Windows Vista).

Mis à jour le 7 mai 2012  par Thibaut Cuvelier

Qt permet grâce aux feuilles de style de définir le style de vos widgets grâce à la fonction setStyleSheet(QString &styleSheet).

Il est également possible de récupérer cette feuille de style avec la fonction styleSheet(), qui renvoie une variable de type QString. De plus, les styles appliqués à un widget sont aussi appliqués à ses widgets enfants.

Utilisation simple des feuilles de styles
Sélectionnez
QPushButton *bouton = new QPushButton("Passez la souris ici !", this);
bouton->setStyleSheet("color: blue;");
setStyleSheet("QPushButton { background-color: #FFFFFF } QPushButton:hover { background-color: #FFD800 } ");
Cibler un widget particulier pour lui appliquer une feuille de style
Sélectionnez
QPushButton *bouton = new QPushButton("Passez la souris ici !", this);
bouton->setObjectName("Bouton");
setStyleSheet("QPushButton#Bouton { color: blue; background-color: #FFFFFF }"
              "QPushButton#Bouton:hover { background-color: #FFD800 } ");

Ici, l'emploi du nom permet d'appliquer une feuille de style à un seul et unique widget.

Cette méthode peut aussi être utilisée sur un QApplication, de sorte que la feuille de style soit appliquée à la totalité de l'application.

La définition d'une feuille de style sur un widget a pour conséquence que tous les enfants de celui-ci en héritent. Par exemple, si vous définissez une telle feuille pour un QFrame, tous les éléments du QFrame en hériteront et seront modifiés en conséquence.

Mis à jour le 7 mai 2012  par Thibaut Cuvelier, Louis du Verdier

Cela dépend de ce que vous voulez faire. Une des solutions adoptées par les développeurs est l'utilisation de la classe QProxyStyle qui hérite directement de QStyle ce qui pousse toutes les fonctions virtuelles du style spécifique aux plateformes :

 
Sélectionnez
class ProxyStyle : public QStyle
    {
    public:
        ProxyStyle(const QString &baseStyle) { style = QStyleFactory::create(baseStyle); }
 
        void polish(QWidget *w) { style->polish(w); }
        void unPolish(QWidget *w) { style->unPolish(w); }
        int pixelMetric(PixelMetric metric, QWidget *widget) const
            { return style->pixelMetric(metric, widget); }
        ...
 
    private:
        QStyle *style;
    };

Alors, il ne suffit plus que d'hériter la sous-classe QProxyStyle et d'implémenter le comportement voulu :

 
Sélectionnez
class MyStyle : public ProxyStyle
    {
    public:
        MyStyle(const QString &baseStyle);
 
        int pixelMetric(PixelMetric metric, const QWidget *widget) const;
    };
 
    int MyStyle::pixelMetric(PixelMetric metric, const QWidget *widget) const
    {
        if (metric == PM_SplitterWidth)
            return 6;
        return ProxyStyle::pixelMetric(metric, widget);
    }

On peut utiliser la classe comme ceci :

 
Sélectionnez
int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        app.setStyle(new MyStyle(app.style().name()));
        ...
        return app.exec();
    }

Grâce à l'approche de proximité, nous ne devons implémenter un comportement personnalisé que dans une seule classe, MyStyle. Une instance de cette classe est alors utilisée pour remplacer le style natif et toutes les fonctions non implémentées dans MyStyle appeleront celle du style natif.

Image non disponible

Effectivement, l'approche de proximité contourne une limitation du C++, qui permet seulement d'hériter des classes à partir d'autres classes et non d'objets. Les classes de proximité sont entièrement expliquées dans le livre Design Patterns (ISBN 0-201-63361-2).

Cette approche a un problème que vous devez connaître. Quelques fonctions virtuelles des styles intégrés à Qt sont implémentées en utilisant d'autres fonctions virtuelles ; par exemple, QWindowStyle::drawCompelxControl() dépend de QWindowsStyle::drawPrimitive() pour dessiner les petites flèches des QComboBox. Si nous réimplémentons drawPrimitive() dans notre classe MyStyle (qui hérite de QProxyStyle), notre réimplémentation sera ignorée par QWindowsStyle, qui va continuer d'appeler sa propre fonction drawPrimitive(). (Ce comportement est dû à MyStyle qui n'hérite pas de QWindowsStyle ; elle ne fait que la recouvrir.) Selon les résultats que l'on veut, nous devons aussi réimplémenter drawComplexControl().

Créé le 7 mai 2012  par Alexandre Laurent

Lien : QProxyStyle
Lien : QProxy

Il est possible d'appliquer un style uniquement aux widgets validant une certaine condition, par exemple en vérifiant qu'une propriété de l'objet est égale à une certaine valeur.

 
Sélectionnez
*[enabled="true"] { background-color: yellow }

On peut alors définir des classes CSS de la manière suivante :

 
Sélectionnez
*[cssclass="class1"] { background-color: blue }
*[cssclass="class2"] { background-color: red }

Notes :

  • Un style est accessible à tous les enfants d'un widget, il faudra donc appliquer celui-ci à un ancêtre commun de tous les widgets utilisant ces classes CSS. ;
  • Le nom cssclass est un choix arbitraire qui peut être remplacé par un autre.

Pour faire appliquer le style défini, il suffit alors de modifier dynamiquement la propriété utilisée dans le CSS (dans notre cas cssclass) :

 
Sélectionnez
_ui->widget1->setProperty("cssclass", "class1");
_ui->widget2->setProperty("cssclass", "class2");
_ui->widget3->setProperty("cssclass", "class2");

Il est également très facile de "désactiver" une classe CSS :

 
Sélectionnez
_ui->widget3->setProperty("cssclass", "");

Un problème cependant, les widgets ne sont pas rafraichis graphiquement lorsqu'on change notre propriété (c'est-à-dire notre classe CSS). Si la classe CSS est appliquée avant que l'on charge le code CSS, nos widgets prennent bien en compte leur classe CSS. Par contre si l'on change leur classe CSS une fois qu'ils sont affichés, rien ne se passe. Une solution est de forcer le rafraichissement graphique du widget comme ceci :

 
Sélectionnez
widget->setProperty("cssclass", "une-classe-css");
widget->style()->unpolish(widget);
widget->style()->polish(widget);
Créé le 7 mai 2012  par Yoann Moreau

Lien : Personnalisation en utilisant des propriétés dynamiques

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2006 - 2017 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.