spinner.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. """
  2. Custom Spinner Widget
  3. A professionally designed animated spinner with rotating arc design.
  4. """
  5. from PyQt5.QtWidgets import QWidget
  6. from PyQt5.QtCore import Qt, QTimer, QRect, QSize
  7. from PyQt5.QtGui import QPainter, QPen, QColor, QBrush
  8. class Spinner(QWidget):
  9. """
  10. A custom rotating spinner widget with smooth arc animation.
  11. Features:
  12. - Smooth rotating arc design
  13. - Customizable colors and sizes
  14. - Professional appearance
  15. """
  16. def __init__(self, parent=None, size: int = 60, color: str = "#3498db"):
  17. """
  18. Initialize the spinner.
  19. Args:
  20. parent: Parent widget
  21. size: Size of the spinner in pixels
  22. color: Color of the spinner (hex or color name)
  23. """
  24. super().__init__(parent)
  25. self.size = size
  26. self.color = QColor(color)
  27. self.angle = 0
  28. self.setMinimumSize(size + 20, size + 20)
  29. self.setMaximumSize(size + 20, size + 20)
  30. # Animation timer
  31. self.timer = QTimer()
  32. self.timer.timeout.connect(self._rotate)
  33. self.timer.start(30) # ~33 FPS for smooth animation
  34. def _rotate(self):
  35. """Update rotation angle."""
  36. self.angle = (self.angle + 6) % 360 # Rotate 6 degrees each frame
  37. self.update()
  38. def paintEvent(self, event):
  39. """Paint the spinner."""
  40. painter = QPainter(self)
  41. painter.setRenderHint(QPainter.Antialiasing)
  42. # Center the spinner
  43. center_x = self.width() // 2
  44. center_y = self.height() // 2
  45. # Draw rotating arc
  46. pen = QPen(self.color)
  47. pen.setWidth(4)
  48. pen.setCapStyle(Qt.RoundCap)
  49. painter.setPen(pen)
  50. # Draw the spinning arc
  51. rect = QRect(center_x - self.size // 2, center_y - self.size // 2, self.size, self.size)
  52. start_angle = self.angle * 16 # Qt uses 1/16 degree units
  53. span_angle = 120 * 16 # 120 degree arc
  54. painter.drawArc(rect, start_angle, span_angle)
  55. # Draw subtle background circle
  56. bg_pen = QPen(QColor("#ecf0f1"))
  57. bg_pen.setWidth(3)
  58. painter.setPen(bg_pen)
  59. painter.drawEllipse(rect)
  60. def stop(self):
  61. """Stop the spinner animation."""
  62. self.timer.stop()
  63. def start(self):
  64. """Start the spinner animation."""
  65. self.timer.start(30)
  66. def set_color(self, color: str):
  67. """
  68. Change the spinner color.
  69. Args:
  70. color: Color in hex or color name
  71. """
  72. self.color = QColor(color)
  73. self.update()
  74. class DotsSpinner(QWidget):
  75. """
  76. An alternative spinner with rotating dots around a circle.
  77. """
  78. def __init__(self, parent=None, size: int = 60, color: str = "#3498db", dot_count: int = 8):
  79. """
  80. Initialize the dots spinner.
  81. Args:
  82. parent: Parent widget
  83. size: Size of the spinner in pixels
  84. color: Color of the spinner dots
  85. dot_count: Number of rotating dots
  86. """
  87. super().__init__(parent)
  88. self.size = size
  89. self.color = QColor(color)
  90. self.angle = 0
  91. self.dot_count = dot_count
  92. self.setMinimumSize(size + 20, size + 20)
  93. self.setMaximumSize(size + 20, size + 20)
  94. # Animation timer
  95. self.timer = QTimer()
  96. self.timer.timeout.connect(self._rotate)
  97. self.timer.start(30)
  98. def _rotate(self):
  99. """Update rotation angle."""
  100. self.angle = (self.angle + 360 / self.dot_count / 8) % 360
  101. self.update()
  102. def paintEvent(self, event):
  103. """Paint the spinner with rotating dots."""
  104. painter = QPainter(self)
  105. painter.setRenderHint(QPainter.Antialiasing)
  106. # Center the spinner
  107. center_x = self.width() // 2
  108. center_y = self.height() // 2
  109. # Draw rotating dots
  110. import math
  111. radius = self.size // 2
  112. dot_radius = 3
  113. for i in range(self.dot_count):
  114. # Calculate angle for this dot
  115. dot_angle = (self.angle + (360 / self.dot_count) * i) * math.pi / 180
  116. # Calculate position
  117. x = center_x + radius * math.cos(dot_angle)
  118. y = center_y + radius * math.sin(dot_angle)
  119. # Fade effect - dots fade out as they come to the back
  120. opacity = (i / self.dot_count + 0.5) % 1.0
  121. color = QColor(self.color)
  122. color.setAlpha(int(255 * opacity))
  123. # Draw dot
  124. painter.setPen(Qt.NoPen)
  125. painter.setBrush(color)
  126. painter.drawEllipse(int(x - dot_radius), int(y - dot_radius),
  127. dot_radius * 2, dot_radius * 2)
  128. def stop(self):
  129. """Stop the spinner animation."""
  130. self.timer.stop()
  131. def start(self):
  132. """Start the spinner animation."""
  133. self.timer.start(30)
  134. def set_color(self, color: str):
  135. """
  136. Change the spinner color.
  137. Args:
  138. color: Color in hex or color name
  139. """
  140. self.color = QColor(color)
  141. self.update()