components.circular_progress_bar

  1from PyQt6.QtCore import Qt, QRectF
  2from PyQt6.QtGui import QColor, QPainter, QPen, QFont
  3from PyQt6.QtWidgets import QWidget
  4
  5
  6class CircularProgress(QWidget):
  7    """
  8    A customizable **circular progress bar widget** for PyQt6 applications.
  9
 10    This widget visually represents a percentage-based progress value (0–100)
 11    as a circular arc with a numeric label at its center. It is lightweight,
 12    anti-aliased, and supports dynamic color changes.
 13
 14    ---
 15    **Features**
 16    - Smooth circular progress rendering with anti-aliasing
 17    - Adjustable color via `setColor()`
 18    - Automatically scales with parent widget size
 19    - Displays numeric percentage text in the center
 20    ---
 21
 22    **Parameters**
 23    - `color (str | QColor)`: Initial color for the progress arc.
 24      Accepts either a hex string (e.g., "#3498DB") or a `QColor` instance.
 25
 26    **Example**
 27    ```python
 28    progress = CircularProgress("#00B894")
 29    progress.setValue(75)
 30    ```
 31    """
 32
 33    def __init__(self, color: str = "#3498DB"):
 34        """
 35        Initialize the circular progress widget.
 36
 37        Args:
 38            color (str): Hex color string for the progress arc (default: "#3498DB").
 39        """
 40        super().__init__()
 41        self.value = 0  # Current progress value (0–100)
 42        self.color = QColor(color)  # Active progress color
 43
 44        self.setMaximumSize(300, 300)
 45
 46    def setValue(self, val: int):
 47        """
 48        Update the progress value and refresh the widget.
 49
 50        Args:
 51            val (int): New progress value (0–100). Values outside this range are clamped.
 52
 53        Notes:
 54            This method triggers a repaint using `update()`.
 55        """
 56        self.value = max(0, min(100, int(val)))
 57        self.update()
 58
 59    def setColor(self, color: str | QColor):
 60        """
 61        Change the color of the progress arc.
 62
 63        Args:
 64            color (str | QColor): The new color for the progress indicator.
 65                                  Can be a hex string or a `QColor` instance.
 66
 67        Example:
 68            ```python
 69            progress.setColor("#E74C3C")  # Set to red
 70            ```
 71        """
 72        if isinstance(color, str):
 73            self.color = QColor(color)
 74        else:
 75            self.color = color
 76        self.update()
 77
 78    def sizeHint(self):
 79        """
 80        Suggest an appropriate default size for the widget.
 81
 82        Returns:
 83            QSize: The preferred size of the widget, matching its parent if available.
 84        """
 85        return self.parentWidget().size() if self.parentWidget() else super().sizeHint()
 86
 87    def paintEvent(self, event):
 88        """
 89        Handle the paint event to draw the circular progress indicator.
 90
 91        The widget draws:
 92        1. A **light gray background circle**
 93        2. A **colored progress arc** proportional to the current value
 94        3. A **percentage label** centered within the circle
 95
 96        Args:
 97            event (QPaintEvent): The paint event object automatically provided by Qt.
 98        """
 99        width = self.width()
100        height = self.height()
101        size = min(width, height)  # Ensure square aspect ratio
102
103        # Center the circle in the available space
104        x_offset = int((width - size) / 2)
105        y_offset = int((height - size) / 2)
106
107        painter = QPainter(self)
108        painter.setRenderHint(QPainter.RenderHint.Antialiasing)
109
110        # --- Draw background circle ---
111        painter.setPen(Qt.PenStyle.NoPen)
112        painter.setBrush(QColor("#f0f0f0"))  # Light gray background
113        painter.drawEllipse(x_offset, y_offset, int(size), int(size))
114
115        # --- Draw progress arc ---
116        pen_width = max(5, int(size / 12))  # Adaptive thickness
117        pen = QPen(self.color)
118        pen.setWidth(pen_width)
119        pen.setCapStyle(Qt.PenCapStyle.RoundCap)
120        painter.setPen(pen)
121        painter.setBrush(Qt.BrushStyle.NoBrush)
122
123        # Define drawing area for the arc
124        rect = QRectF(
125            x_offset + pen_width / 2,
126            y_offset + pen_width / 2,
127            size - pen_width,
128            size - pen_width
129        )
130        angle_span = int(360 * self.value / 100)
131        painter.drawArc(rect, -90 * 16, -angle_span * 16)  # Start from top center
132
133        # --- Draw percentage text ---
134        font_size = max(5, int(size / 9))
135        painter.setPen(QColor("#2C3E50"))  # Dark blue-gray text
136        painter.setFont(QFont("Arial", font_size, QFont.Weight.Bold))
137        painter.drawText(rect, Qt.AlignmentFlag.AlignCenter, f"{self.value}%")
class CircularProgress(PyQt6.QtWidgets.QWidget):
  7class CircularProgress(QWidget):
  8    """
  9    A customizable **circular progress bar widget** for PyQt6 applications.
 10
 11    This widget visually represents a percentage-based progress value (0–100)
 12    as a circular arc with a numeric label at its center. It is lightweight,
 13    anti-aliased, and supports dynamic color changes.
 14
 15    ---
 16    **Features**
 17    - Smooth circular progress rendering with anti-aliasing
 18    - Adjustable color via `setColor()`
 19    - Automatically scales with parent widget size
 20    - Displays numeric percentage text in the center
 21    ---
 22
 23    **Parameters**
 24    - `color (str | QColor)`: Initial color for the progress arc.
 25      Accepts either a hex string (e.g., "#3498DB") or a `QColor` instance.
 26
 27    **Example**
 28    ```python
 29    progress = CircularProgress("#00B894")
 30    progress.setValue(75)
 31    ```
 32    """
 33
 34    def __init__(self, color: str = "#3498DB"):
 35        """
 36        Initialize the circular progress widget.
 37
 38        Args:
 39            color (str): Hex color string for the progress arc (default: "#3498DB").
 40        """
 41        super().__init__()
 42        self.value = 0  # Current progress value (0–100)
 43        self.color = QColor(color)  # Active progress color
 44
 45        self.setMaximumSize(300, 300)
 46
 47    def setValue(self, val: int):
 48        """
 49        Update the progress value and refresh the widget.
 50
 51        Args:
 52            val (int): New progress value (0–100). Values outside this range are clamped.
 53
 54        Notes:
 55            This method triggers a repaint using `update()`.
 56        """
 57        self.value = max(0, min(100, int(val)))
 58        self.update()
 59
 60    def setColor(self, color: str | QColor):
 61        """
 62        Change the color of the progress arc.
 63
 64        Args:
 65            color (str | QColor): The new color for the progress indicator.
 66                                  Can be a hex string or a `QColor` instance.
 67
 68        Example:
 69            ```python
 70            progress.setColor("#E74C3C")  # Set to red
 71            ```
 72        """
 73        if isinstance(color, str):
 74            self.color = QColor(color)
 75        else:
 76            self.color = color
 77        self.update()
 78
 79    def sizeHint(self):
 80        """
 81        Suggest an appropriate default size for the widget.
 82
 83        Returns:
 84            QSize: The preferred size of the widget, matching its parent if available.
 85        """
 86        return self.parentWidget().size() if self.parentWidget() else super().sizeHint()
 87
 88    def paintEvent(self, event):
 89        """
 90        Handle the paint event to draw the circular progress indicator.
 91
 92        The widget draws:
 93        1. A **light gray background circle**
 94        2. A **colored progress arc** proportional to the current value
 95        3. A **percentage label** centered within the circle
 96
 97        Args:
 98            event (QPaintEvent): The paint event object automatically provided by Qt.
 99        """
100        width = self.width()
101        height = self.height()
102        size = min(width, height)  # Ensure square aspect ratio
103
104        # Center the circle in the available space
105        x_offset = int((width - size) / 2)
106        y_offset = int((height - size) / 2)
107
108        painter = QPainter(self)
109        painter.setRenderHint(QPainter.RenderHint.Antialiasing)
110
111        # --- Draw background circle ---
112        painter.setPen(Qt.PenStyle.NoPen)
113        painter.setBrush(QColor("#f0f0f0"))  # Light gray background
114        painter.drawEllipse(x_offset, y_offset, int(size), int(size))
115
116        # --- Draw progress arc ---
117        pen_width = max(5, int(size / 12))  # Adaptive thickness
118        pen = QPen(self.color)
119        pen.setWidth(pen_width)
120        pen.setCapStyle(Qt.PenCapStyle.RoundCap)
121        painter.setPen(pen)
122        painter.setBrush(Qt.BrushStyle.NoBrush)
123
124        # Define drawing area for the arc
125        rect = QRectF(
126            x_offset + pen_width / 2,
127            y_offset + pen_width / 2,
128            size - pen_width,
129            size - pen_width
130        )
131        angle_span = int(360 * self.value / 100)
132        painter.drawArc(rect, -90 * 16, -angle_span * 16)  # Start from top center
133
134        # --- Draw percentage text ---
135        font_size = max(5, int(size / 9))
136        painter.setPen(QColor("#2C3E50"))  # Dark blue-gray text
137        painter.setFont(QFont("Arial", font_size, QFont.Weight.Bold))
138        painter.drawText(rect, Qt.AlignmentFlag.AlignCenter, f"{self.value}%")

A customizable circular progress bar widget for PyQt6 applications.

This widget visually represents a percentage-based progress value (0–100) as a circular arc with a numeric label at its center. It is lightweight, anti-aliased, and supports dynamic color changes.


Features

  • Smooth circular progress rendering with anti-aliasing
  • Adjustable color via setColor()
  • Automatically scales with parent widget size

- Displays numeric percentage text in the center

Parameters

  • color (str | QColor): Initial color for the progress arc. Accepts either a hex string (e.g., "#3498DB") or a QColor instance.

Example

progress = CircularProgress("#00B894")
progress.setValue(75)
CircularProgress(color: str = '#3498DB')
34    def __init__(self, color: str = "#3498DB"):
35        """
36        Initialize the circular progress widget.
37
38        Args:
39            color (str): Hex color string for the progress arc (default: "#3498DB").
40        """
41        super().__init__()
42        self.value = 0  # Current progress value (0–100)
43        self.color = QColor(color)  # Active progress color
44
45        self.setMaximumSize(300, 300)

Initialize the circular progress widget.

Args: color (str): Hex color string for the progress arc (default: "#3498DB").

value
color
def setValue(self, val: int):
47    def setValue(self, val: int):
48        """
49        Update the progress value and refresh the widget.
50
51        Args:
52            val (int): New progress value (0–100). Values outside this range are clamped.
53
54        Notes:
55            This method triggers a repaint using `update()`.
56        """
57        self.value = max(0, min(100, int(val)))
58        self.update()

Update the progress value and refresh the widget.

Args: val (int): New progress value (0–100). Values outside this range are clamped.

Notes: This method triggers a repaint using update().

def setColor(self, color: str | PyQt6.QtGui.QColor):
60    def setColor(self, color: str | QColor):
61        """
62        Change the color of the progress arc.
63
64        Args:
65            color (str | QColor): The new color for the progress indicator.
66                                  Can be a hex string or a `QColor` instance.
67
68        Example:
69            ```python
70            progress.setColor("#E74C3C")  # Set to red
71            ```
72        """
73        if isinstance(color, str):
74            self.color = QColor(color)
75        else:
76            self.color = color
77        self.update()

Change the color of the progress arc.

Args: color (str | QColor): The new color for the progress indicator. Can be a hex string or a QColor instance.

Example:

progress.setColor("#E74C3C")  # Set to red
def sizeHint(self):
79    def sizeHint(self):
80        """
81        Suggest an appropriate default size for the widget.
82
83        Returns:
84            QSize: The preferred size of the widget, matching its parent if available.
85        """
86        return self.parentWidget().size() if self.parentWidget() else super().sizeHint()

Suggest an appropriate default size for the widget.

Returns: QSize: The preferred size of the widget, matching its parent if available.

def paintEvent(self, event):
 88    def paintEvent(self, event):
 89        """
 90        Handle the paint event to draw the circular progress indicator.
 91
 92        The widget draws:
 93        1. A **light gray background circle**
 94        2. A **colored progress arc** proportional to the current value
 95        3. A **percentage label** centered within the circle
 96
 97        Args:
 98            event (QPaintEvent): The paint event object automatically provided by Qt.
 99        """
100        width = self.width()
101        height = self.height()
102        size = min(width, height)  # Ensure square aspect ratio
103
104        # Center the circle in the available space
105        x_offset = int((width - size) / 2)
106        y_offset = int((height - size) / 2)
107
108        painter = QPainter(self)
109        painter.setRenderHint(QPainter.RenderHint.Antialiasing)
110
111        # --- Draw background circle ---
112        painter.setPen(Qt.PenStyle.NoPen)
113        painter.setBrush(QColor("#f0f0f0"))  # Light gray background
114        painter.drawEllipse(x_offset, y_offset, int(size), int(size))
115
116        # --- Draw progress arc ---
117        pen_width = max(5, int(size / 12))  # Adaptive thickness
118        pen = QPen(self.color)
119        pen.setWidth(pen_width)
120        pen.setCapStyle(Qt.PenCapStyle.RoundCap)
121        painter.setPen(pen)
122        painter.setBrush(Qt.BrushStyle.NoBrush)
123
124        # Define drawing area for the arc
125        rect = QRectF(
126            x_offset + pen_width / 2,
127            y_offset + pen_width / 2,
128            size - pen_width,
129            size - pen_width
130        )
131        angle_span = int(360 * self.value / 100)
132        painter.drawArc(rect, -90 * 16, -angle_span * 16)  # Start from top center
133
134        # --- Draw percentage text ---
135        font_size = max(5, int(size / 9))
136        painter.setPen(QColor("#2C3E50"))  # Dark blue-gray text
137        painter.setFont(QFont("Arial", font_size, QFont.Weight.Bold))
138        painter.drawText(rect, Qt.AlignmentFlag.AlignCenter, f"{self.value}%")

Handle the paint event to draw the circular progress indicator.

The widget draws:

  1. A light gray background circle
  2. A colored progress arc proportional to the current value
  3. A percentage label centered within the circle

Args: event (QPaintEvent): The paint event object automatically provided by Qt.