Fond translucide
L'exemple montre comment créer une fenêtre ronde avec un arrière-plan translucide.

Les widgets dont l'arrière-plan est translucide sont transparents pour tous les pixels non peints, et l'arrière-plan transparaît sur les pixels peints avec une opacité inférieure à 100 %. Les pixels qui ne sont pas peints du tout ne recevront pas non plus d'entrée de la souris. Ceci peut être utilisé pour personnaliser les formes des widgets de niveau supérieur. Sur la plupart des systèmes de fenêtres, l'activation de certains drapeaux de fenêtre entraîne la désactivation de la décoration de la fenêtre (barre de titre, cadre de la fenêtre, boutons), ce qui permet de créer des fenêtres de forme spéciale. Dans cet exemple, nous utilisons cette fonctionnalité pour créer une fenêtre circulaire contenant une horloge analogique.
Étant donné que la fenêtre de cet exemple ne comporte pas de menu File ni de bouton de fermeture, nous proposons un menu contextuel avec une entrée Exit afin de pouvoir fermer l'exemple. Cliquez avec le bouton droit de la souris sur la fenêtre pour ouvrir ce menu.
Définition de la classe ShapedClock
La classe ShapedClock est basée sur la classe AnalogClock définie dans l'exemple de l'horloge analogique. La définition complète de la classe est présentée ci-dessous :
class ShapedClock : public QWidget { Q_OBJECT public: ShapedClock(QWidget *parent = nullptr); QSize sizeHint() const override; protected: void mouseMoveEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void paintEvent(QPaintEvent *event) override; private: QPoint dragPosition; };
L'implémentation de paintEvent() dessine une horloge analogique sur un fond semi-transparent (le cadran de l'horloge). En outre, nous implémentons sizeHint() afin de ne pas avoir à redimensionner le widget explicitement.
Étant donné que la fenêtre contenant le widget horloge n'aura pas de barre de titre, nous fournissons des implémentations pour mouseMoveEvent() et mousePressEvent() afin de permettre à l'horloge d'être déplacée sur l'écran. La variable dragPosition nous permet de savoir où l'utilisateur a cliqué pour la dernière fois sur le widget.
Mise en œuvre de la classe ShapedClock
Le constructeur de ShapedClock met en place une minuterie et la connecte au slot update() du widget. En outre, nous ajoutons une action au widget, qui sera automatiquement disponible dans un menu contextuel lors d'un clic droit sur le widget.
ShapedClock::ShapedClock(QWidget *parent) : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowSystemMenuHint) { setAttribute(Qt::WA_TranslucentBackground); QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, QOverload<>::of(&ShapedClock::update)); timer->start(1000); QAction *quitAction = new QAction(tr("E&xit"), this); quitAction->setShortcut(tr("Ctrl+Q")); connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit); addAction(quitAction); setContextMenuPolicy(Qt::ActionsContextMenu); setToolTip(tr("Drag the clock with the left mouse button.\n" "Use the right mouse button to open a context menu.")); setWindowTitle(tr("Shaped Analog Clock")); }
Nous demandons une fenêtre transparente en définissant l'attribut de widget Qt::WA_TranslucentBackground. Nous informons le gestionnaire de fenêtres que le widget ne doit pas être décoré d'un cadre de fenêtre en définissant le drapeau Qt::FramelessWindowHint sur le widget. Par conséquent, nous devons fournir à l'utilisateur un moyen de déplacer l'horloge sur l'écran.
Les événements liés au bouton de la souris sont transmis au gestionnaire mousePressEvent():
void ShapedClock::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { dragPosition = event->globalPosition().toPoint() - frameGeometry().topLeft(); event->accept(); } }
Si le bouton gauche de la souris est pressé sur le widget, nous enregistrons le déplacement en coordonnées globales (écran) entre la position en haut à gauche du cadre du widget (même lorsqu'il est caché) et le point où le clic de la souris s'est produit. Ce déplacement sera utilisé si l'utilisateur déplace la souris tout en maintenant le bouton gauche enfoncé. Puisque nous avons agi sur l'événement, nous l'acceptons en appelant sa fonction accept().

Le gestionnaire mouseMoveEvent() est appelé si la souris est déplacée sur le widget.
void ShapedClock::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) { move(event->globalPosition().toPoint() - dragPosition); event->accept(); } }
Si le bouton gauche est maintenu enfoncé pendant que la souris est déplacée, le coin supérieur gauche du widget est déplacé au point donné par la soustraction de dragPosition à la position actuelle du curseur en coordonnées globales. Si nous faisons glisser le widget, nous acceptons également l'événement.
La fonction paintEvent() est principalement la même que celle décrite dans l'exemple de l'horloge analogique. La seule nouveauté est que nous utilisons QPainter::drawEllipse() pour dessiner un cadran d'horloge rond. Nous réduisons l'opacité du peintre à 90 % et utilisons la couleur d'arrière-plan par défaut de la palette.
void ShapedClock::paintEvent(QPaintEvent *) { static const QPoint hourHand[4] = { QPoint(5, 14), QPoint(-5, 14), QPoint(-4, -71), QPoint(4, -71) }; static const QPoint minuteHand[4] = { QPoint(4, 14), QPoint(-4, 14), QPoint(-3, -89), QPoint(3, -89) }; static const QPoint secondsHand[4] = { QPoint(1, 14), QPoint(-1, 14), QPoint(-1, -89), QPoint(1, -89) }; const QColor hourColor(palette().color(QPalette::Text)); const QColor minuteColor(palette().color(QPalette::Text)); const QColor secondsColor(palette().color(QPalette::Accent)); int side = qMin(width(), height()); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.translate(width() / 2, height() / 2); painter.scale(side / 200.0, side / 200.0); painter.setPen(Qt::NoPen); painter.setBrush(palette().window()); painter.setOpacity(0.9); painter.drawEllipse(QPoint(0, 0), 98, 98); painter.setOpacity(1.0); QTime time = QTime::currentTime(); painter.setPen(Qt::NoPen); painter.setBrush(hourColor); { QPainterStateGuard guard(&painter); painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0))); painter.drawConvexPolygon(hourHand, 4); } for (int i = 0; i < 12; ++i) { painter.drawRect(73, -3, 16, 6); painter.rotate(30.0); } painter.setBrush(minuteColor); { QPainterStateGuard guard(&painter); painter.rotate(6.0 * time.minute()); painter.drawConvexPolygon(minuteHand, 4); } painter.setBrush(secondsColor); { QPainterStateGuard guard(&painter); painter.rotate(6.0 * time.second()); painter.drawConvexPolygon(secondsHand, 4); painter.drawEllipse(-3, -3, 6, 6); painter.drawEllipse(-5, -68, 10, 10); } painter.setPen(minuteColor); for (int j = 0; j < 60; ++j) { painter.drawLine(92, 0, 96, 0); painter.rotate(6.0); } }
Enfin, nous implémentons sizeHint() pour le widget afin qu'il ait une taille par défaut raisonnable lorsqu'il est affiché pour la première fois :
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.