Source code for pygame_menu.widgets.widget.progressbar

"""
pygame-menu
https://github.com/ppizarror/pygame-menu

PROGRESS BAR
Progress bar widget.
"""

__all__ = [

    # Class
    'ProgressBar',

    # Types
    'ProgressBarTextFormatType'

]

import pygame
import pygame_menu

from pygame_menu.font import FontType, assert_font
from pygame_menu.locals import ALIGN_LEFT, ALIGN_CENTER
from pygame_menu.utils import assert_color, assert_vector, make_surface, \
    is_callable, assert_alignment, parse_padding
from pygame_menu.widgets.core.widget import Widget, WidgetTransformationNotImplemented

from pygame_menu._types import Any, CallbackType, Optional, ColorType, NumberType, \
    Tuple2IntType, NumberInstance, ColorInputType, EventVectorType, Callable, \
    PaddingType, Tuple4IntType

ProgressBarTextFormatType = Callable[[NumberType], str]


# noinspection PyMissingOrEmptyDocstring
[docs]class ProgressBar(Widget): """ Progress bar widget, offers a bar that accepts a percentage from ``0`` to ``100``. .. note:: ProgressBar only accepts translation transformation. :param title: Progressbar title :param progressbar_id: ProgressBar ID :param default: Default value of the progressbar, from ``0`` to ``100`` :param width: Progress bar width in px :param onselect: Function when selecting the widget :param box_background_color: Background color of the box :param box_border_color: Border color of the box :param box_border_width: Border width of the box in px :param box_margin: Box margin on x-axis and y-axis (x, y) respect to the title of the widget in px :param box_progress_color: Box progress color :param box_progress_padding: Box progress padding :param progress_text_align: Align of the progress text, can be CENTER, LEFT or RIGHT. See :py:mod:`pygame_menu.locals` :param progress_text_enabled: Enables the progress text over box :param progress_text_font: Progress font. If ``None`` uses the same as the widget font :param progress_text_font_color: Progress font color. If ``None`` uses the same as the widget font :param progress_text_font_hfactor: Height factor of the font height relative to the widget font height :param progress_text_format: Format function of the progress text, which considers as input the progress value (0-100) :param progress_text_margin: Margin of the progress box on x-axis and y-axis in px :param progress_text_placeholder: Placeholder of the progress text, which considers as format the output of ``progress_text_format`` :param args: Optional arguments for callbacks :param kwargs: Optional keyword arguments """ _box: 'pygame.Surface' _box_background_color: ColorType _box_border_color: ColorType _box_border_width: int _box_height: int _box_margin: Tuple2IntType _box_pos: int _box_progress_color: ColorType _box_progress_padding: Tuple4IntType _progress: NumberType _progress_font: FontType _progress_text_align: str _progress_text_enabled: bool _progress_text_font: Optional[FontType] _progress_text_font_color: ColorType _progress_text_font_height: int _progress_text_font_height_factor: float _progress_text_format: ProgressBarTextFormatType _progress_text_margin: Tuple2IntType _progress_text_placeholder: str _width: int def __init__( self, title: Any, progressbar_id: str = '', default: NumberType = 0, width: int = 150, onselect: CallbackType = None, box_background_color: ColorInputType = (255, 255, 255), box_border_color: ColorInputType = (0, 0, 0), box_border_width: int = 1, box_margin: Tuple2IntType = (25, 0), box_progress_color: ColorInputType = (0, 255, 0), box_progress_padding: PaddingType = (1, 1), progress_text_align: str = ALIGN_CENTER, progress_text_enabled: bool = True, progress_text_font: Optional[FontType] = None, progress_text_font_color: ColorInputType = (0, 0, 0), progress_text_font_hfactor: float = 0.8, progress_text_format: ProgressBarTextFormatType = lambda x: str(round(x, 1)), progress_text_margin: Tuple2IntType = (0, 0), progress_text_placeholder: str = '{0} %', *args, **kwargs ) -> None: super(ProgressBar, self).__init__( args=args, kwargs=kwargs, onselect=onselect, title=title, widget_id=progressbar_id ) # Check the value assert isinstance(default, NumberInstance) assert 0 <= default <= 100, 'default value must range from 0 to 100' # Check fonts if progress_text_font is not None: assert_font(progress_text_font) assert isinstance(progress_text_font_hfactor, NumberInstance) assert progress_text_font_hfactor > 0, \ 'progress text font height factor must be greater than zero' # Check colors box_background_color = assert_color(box_background_color) box_border_color = assert_color(box_border_color) box_progress_color = assert_color(box_progress_color) progress_text_font_color = assert_color(progress_text_font_color) # Check dimensions and sizes assert isinstance(box_border_width, int) assert box_border_width >= 0, \ 'box border width must be equal or greater than zero' assert_vector(box_margin, 2, int) assert_vector(progress_text_margin, 2, int) assert isinstance(width, int) assert width > 0, 'width must be greater than zero' box_progress_padding = parse_padding(box_progress_padding) self._box_progress_padding = box_progress_padding # Check progress text assert isinstance(progress_text_enabled, bool) assert is_callable(progress_text_format) assert isinstance(progress_text_format(0), str) assert isinstance(progress_text_placeholder, str) assert_alignment(progress_text_align) # Store properties self._default_value = default self._box_background_color = box_background_color self._box_border_color = box_border_color self._box_border_width = box_border_width self._box_margin = box_margin self._box_progress_color = box_progress_color self._progress = default self._progress_text_align = progress_text_align self._progress_text_enabled = progress_text_enabled self._progress_text_font = progress_text_font self._progress_text_font_color = progress_text_font_color self._progress_text_font_height = 0 self._progress_text_font_height_factor = progress_text_font_hfactor self._progress_text_format = progress_text_format self._progress_text_margin = progress_text_margin self._progress_text_placeholder = progress_text_placeholder self._width = width
[docs] def set_value(self, value: NumberType) -> None: assert isinstance(value, NumberInstance), 'progress value must be numeric' assert 0 <= value <= 100, 'value must be between 0 and 100' self._progress = value self._render()
def scale(self, *args, **kwargs) -> 'ProgressBar': raise WidgetTransformationNotImplemented() def resize(self, *args, **kwargs) -> 'ProgressBar': raise WidgetTransformationNotImplemented() def set_max_width(self, *args, **kwargs) -> 'ProgressBar': raise WidgetTransformationNotImplemented() def set_max_height(self, *args, **kwargs) -> 'ProgressBar': raise WidgetTransformationNotImplemented() def rotate(self, *args, **kwargs) -> 'ProgressBar': raise WidgetTransformationNotImplemented() def flip(self, *args, **kwargs) -> 'ProgressBar': raise WidgetTransformationNotImplemented()
[docs] def get_value(self) -> NumberType: return self._progress
def _apply_font(self) -> None: if self._progress_text_font is None: self._progress_text_font = self._font_name self._progress_text_font_height = int(self._font_size * self._progress_text_font_height_factor) self._progress_font = pygame_menu.font.get_font( self._progress_text_font, self._progress_text_font_height ) self._box_height = self._font_render_string('TEST').get_height() def _draw(self, surface: 'pygame.Surface') -> None: # Draw title surface.blit(self._surface, (self._rect.x, self._rect.y)) # Draw box box_rect = self._box.get_rect() box_rect.x += self._rect.x + self._box_margin[0] + self._box_pos box_rect.y += self._rect.y + self._box_margin[1] surface.blit(self._box, box_rect) # Draw box border if self._box_border_width > 0: pygame.draw.rect(surface, self._box_border_color, box_rect, self._box_border_width) def _render(self) -> Optional[bool]: if not hasattr(self, '_progress_font'): return False if not self._render_hash_changed( self._selected, self._title, self._visible, self.readonly, self._progress): return True # Create basic title self._surface = self._render_string(self._title, self.get_font_color_status()) self._rect.width, self._rect.height = self._surface.get_size() # Create box self._box = make_surface(self._width, self._box_height, fill_color=self._box_background_color) box_progress = make_surface(int(self._width * self._progress / 100), self._box_height - self._box_progress_padding[0] - self._box_progress_padding[2], fill_color=self._box_progress_color) self._box.blit(box_progress, (self._box_progress_padding[1], self._box_progress_padding[0])) self._box_pos = self._rect.width # Create progress text text = self._progress_font.render( self._progress_text_placeholder.format(self._progress_text_format(self._progress)), self._font_antialias, self._progress_text_font_color ) text_y = int((self._box_height - text.get_height()) / 2) if self._progress_text_align == ALIGN_LEFT: text_x = self._box_progress_padding[1] elif self._progress_text_align == ALIGN_CENTER: text_x = int((self._width - text.get_width()) / 2) else: text_x = self._width - self._box_progress_padding[3] - text.get_width() text_x += self._progress_text_margin[0] text_y += self._progress_text_margin[1] if self._progress_text_enabled: self._box.blit(text, (text_x, text_y)) # Update maximum rect height self._rect.height = max(self._rect.height, self._box.get_height()) self._rect.width += self._width + self._box_margin[0] # Finals self.force_menu_surface_update()
[docs] def update(self, events: EventVectorType) -> bool: self.apply_update_callbacks(events) return False