Nous allons, dans ce nouveau chapitre voir comment mettre en oeuvre un widget de type « horloge à aiguilles ». La capture d'écran suivant vous montre le résultat visé.
Et voici le code de notre nouveau widget.
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 |
import math import sys from datetime import datetime from PySide6.QtGui import QPainter, QColor, QCloseEvent, QLinearGradient, QPen from PySide6.QtCore import QPoint, Qt, QPointF, QTimer from PySide6.QtGui import QPaintEvent from PySide6.QtWidgets import QMainWindow, QWidget, QApplication class ClockWidget(QWidget): def __init__(self): super().__init__() self.__timer = QTimer(self) self.__timer.timeout.connect(self.repaint) self.__timer.start(1000) def closeEvent(self, event:QCloseEvent) -> None: self.__timer.stop() def paintEvent(self, event:QPaintEvent) -> None: super().paintEvent(event) painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing); # On dessine le cercle de l'horloge avec un dégradé autour radius = 0.95 * (min(self.width(), self.height()) / 2) centerX = int(self.width() / 2) centerY = int(self.height() / 2) linearGradient = QLinearGradient(QPointF(0, 0), QPointF(0, radius*2)) linearGradient.setColorAt(0, QColor(0xE0, 0xE0, 0xE0)) linearGradient.setColorAt(0.5, QColor(0x6E, 0x77, 0x74)) linearGradient.setColorAt(0.51, QColor(0x0a, 0x0e, 0x0a)) linearGradient.setColorAt(1, QColor(0x0a, 0x08, 0x09)) painter.setPen(QPen(linearGradient, 8)) painter.setBrush(QColor(0x21, 0x21, 0x21)) painter.drawEllipse(QPoint(centerX, centerY), radius, radius) # On s'apprète à dessiner les graduations sur l'horloge font = painter.font() font.setPointSize(16) painter.setFont(font) angle = -math.pi / 2 + math.pi / 30 hour = 1 for step in range(12 * 5): angle += math.pi / 30 hour += 1 painter.setPen(Qt.white) painter.setBrush(Qt.white) if hour % 5 == 0: # Tracé d'une graduation d'heure painter.drawPolygon([ QPointF(centerX + math.cos(angle - 0.02) * radius * 0.9, centerY + math.sin(angle - 0.02) * radius * 0.9), QPointF(centerX + math.cos(angle - 0.01) * radius * 0.8, centerY + math.sin(angle - 0.01) * radius * 0.8), QPointF(centerX + math.cos(angle + 0.01) * radius * 0.8, centerY + math.sin(angle + 0.01) * radius * 0.8), QPointF(centerX + math.cos(angle + 0.02) * radius * 0.9, centerY + math.sin(angle + 0.02) * radius * 0.9) ]) delta = radius * 0.04 painter.drawText(int(centerX + math.cos(angle) * radius * 0.7) - 8, int(centerY + math.sin(angle) * radius * 0.7 + delta), str(hour // 5)) else: # Tracé d'une graduation de minute painter.drawLine( QPointF(centerX + math.cos(angle) * radius * 0.85, centerY + math.sin(angle) * radius * 0.85), QPointF(centerX + math.cos(angle) * radius * 0.9, centerY + math.sin(angle) * radius * 0.9) ) now = datetime.now() # On dessine la trotteuse painter.setPen(QPen(QColor(255, 0, 0, int(256 * 0.6)), 3)) angle = - math.pi / 2 + now.second * math.pi / 30 destX = math.cos(angle) * radius * 0.95 destY = math.sin(angle) * radius * 0.95 painter.drawLine(centerX, centerY, int(centerX + destX), int(centerY + destY)) # On dessine l'aiguille des minutes painter.setPen(QColor(255, 0, 0)) painter.setBrush(QColor(255, 0, 0, 150)) minuteAngle = math.pi * 2 * (now.minute / 60 + now.second / 3600) minuteAngle = -(math.pi / 2 - minuteAngle) painter.drawPolygon([ QPointF(centerX + math.cos(minuteAngle) * radius * 0.93, centerY + math.sin(minuteAngle) * radius * 0.93), QPointF(centerX + math.cos(minuteAngle - 0.4) * radius * 0.1, centerY + math.sin(minuteAngle - 0.4) * radius * 0.1), QPointF(centerX + math.cos(minuteAngle + 0.4) * radius * 0.1, centerY + math.sin(minuteAngle + 0.4) * radius * 0.1) ]) # On dessine l'aiguille des heures hourAngle = math.pi * 2 * ((now.hour % 12 + now.minute / 60) / 12) hourAngle = -(math.pi / 2 - hourAngle) painter.drawPolygon([ QPointF(centerX + math.cos(hourAngle) * radius * 0.6, centerY + math.sin(hourAngle) * radius * 0.6), QPointF(centerX + math.cos(hourAngle - 0.3) * radius * 0.1, centerY + math.sin(hourAngle - 0.3) * radius * 0.1), QPointF(centerX + math.cos(hourAngle + 0.3) * radius * 0.1, centerY + math.sin(hourAngle + 0.3) * radius * 0.1) ]) # On dessine le disque interne painter.setPen(QPen(linearGradient, 8)) painter.setBrush(QColor(0x21, 0x21, 0x21)) painter.drawEllipse(QPoint(centerX, centerY), radius * 0.18, radius * 0.18) class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("Exemple de création d'un Widget Horloge") self.resize(400, 400) # On instancie notre nouveau widget et on l'ajoute à la fenêtre clock = ClockWidget() self.setCentralWidget(clock) if __name__ == '__main__': app = QApplication(sys.argv) mainWindow = MainWindow() mainWindow.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 :