switch.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. from PyQt6.QtWidgets import QCheckBox
  2. from PyQt6.QtCore import (
  3. Qt,
  4. QPropertyAnimation,
  5. pyqtProperty,
  6. QRectF,
  7. QSize
  8. )
  9. from PyQt6.QtGui import QPainter, QColor
  10. class Switch(QCheckBox):
  11. def __init__(self, parent=None):
  12. super().__init__(parent)
  13. self.setCursor(Qt.CursorShape.PointingHandCursor)
  14. self.setFixedSize(50, 26)
  15. self._offset = 3
  16. self._radius = 10
  17. self._animation = QPropertyAnimation(self, b"offset", self)
  18. self._animation.setDuration(180)
  19. self._bg_off = QColor("#bdc3c7")
  20. self._bg_on = QColor("#2ecc71")
  21. self._circle_color = QColor("white")
  22. self.toggled.connect(self.start_transition)
  23. self.setTristate(False)
  24. self.setText("")
  25. # Taille recommandée
  26. def sizeHint(self):
  27. return QSize(50, 26)
  28. # Animation
  29. def start_transition(self, checked):
  30. self._animation.stop()
  31. start = self._offset
  32. end = self.width() - self._radius*2 - 3 if checked else 3
  33. self._animation.setStartValue(start)
  34. self._animation.setEndValue(end)
  35. self._animation.start()
  36. # Dessin
  37. def paintEvent(self, event):
  38. painter = QPainter(self)
  39. painter.setRenderHint(QPainter.RenderHint.Antialiasing)
  40. # Background
  41. if self.isChecked():
  42. painter.setBrush(self._bg_on)
  43. else:
  44. painter.setBrush(self._bg_off)
  45. painter.setPen(Qt.PenStyle.NoPen)
  46. painter.drawRoundedRect(
  47. 0, 0,
  48. self.width(),
  49. self.height(),
  50. self.height() / 2,
  51. self.height() / 2
  52. )
  53. # Cercle
  54. painter.setBrush(self._circle_color)
  55. painter.drawEllipse(
  56. QRectF(
  57. self._offset,
  58. (self.height() - self._radius*2)/2,
  59. self._radius*2,
  60. self._radius*2
  61. )
  62. )
  63. # Property animable
  64. def get_offset(self):
  65. return self._offset
  66. def mouseReleaseEvent(self, event):
  67. if event.button() == Qt.MouseButton.LeftButton:
  68. self.setChecked(not self.isChecked())
  69. super().mouseReleaseEvent(event)
  70. def set_offset(self, value):
  71. self._offset = value
  72. self.update()
  73. offset = pyqtProperty(float, get_offset, set_offset)