"""
pygame-menu
https://github.com/ppizarror/pygame-menu
IMAGE
Image widget class, adds a simple image.
"""
__all__ = ['Image']
from io import BytesIO
from pathlib import Path
import pygame
from pygame_menu.baseimage import BaseImage
from pygame_menu.utils import assert_vector
from pygame_menu.widgets.core.widget import Widget
from pygame_menu._types import Union, NumberType, CallbackType, Tuple2NumberType, \
Optional, NumberInstance, EventVectorType
# noinspection PyMissingOrEmptyDocstring
[docs]class Image(Widget):
"""
Image widget.
.. note::
Image accepts all transformations.
:param image_path: Path of the image, BytesIO object, or :py:class:`pygame_menu.baseimage.BaseImage` object. If :py:class:`pygame_menu.baseimage.BaseImage` object is provided drawing mode is not considered
:param image_id: Image ID
:param angle: Angle of the image in degrees (clockwise)
:param onselect: Function when selecting the widget
:param scale: Scale of the image on x-axis and y-axis (x, y) in px
:param scale_smooth: Scale is smoothed
"""
_image: 'BaseImage'
def __init__(
self,
image_path: Union[str, 'BaseImage', 'Path', 'BytesIO'],
angle: NumberType = 0,
image_id: str = '',
onselect: CallbackType = None,
scale: Tuple2NumberType = (1, 1),
scale_smooth: bool = True
) -> None:
assert isinstance(image_path, (str, Path, BaseImage, BytesIO))
assert isinstance(image_id, str)
assert isinstance(angle, NumberInstance)
assert isinstance(scale_smooth, bool)
assert_vector(scale, 2)
super(Image, self).__init__(
onselect=onselect,
widget_id=image_id
)
if isinstance(image_path, BaseImage):
self._image = image_path
else:
self._image = BaseImage(image_path)
self._image.rotate(angle)
self._image.scale(scale[0], scale[1], smooth=scale_smooth)
def set_title(self, title: str) -> 'Image':
return self
[docs] def get_image(self) -> 'BaseImage':
"""
Gets the :py:class:`pygame_menu.baseimage.BaseImage` object from widget.
:return: Widget image
"""
return self._image
[docs] def get_angle(self) -> NumberType:
"""
Return the image angle.
:return: Angle in degrees
"""
return self._image.get_angle()
[docs] def set_image(self, image: 'BaseImage') -> None:
"""
Set the :py:class:`pygame_menu.baseimage.BaseImage` object from widget.
:param image: Image object
:return: None
"""
self._image = image
self._surface = None
self._render()
def _apply_font(self) -> None:
pass
def _update_surface(self) -> 'Image':
"""
Updates surface and renders.
:return: Self reference
"""
self._surface = None
self._render()
return self
[docs] def scale(self, width: NumberType, height: NumberType, smooth: bool = False) -> 'Image':
self._image.scale(width, height, smooth)
return self._update_surface()
[docs] def resize(self, width: NumberType, height: NumberType, smooth: bool = False) -> 'Image':
self._image.resize(width, height, smooth)
self._surface = None
return self._update_surface()
[docs] def set_max_width(self, width: Optional[NumberType], scale_height: NumberType = False,
smooth: bool = True) -> 'Image':
if width is not None and self._image.get_width() > width:
sx = width / self._image.get_width()
height = self._image.get_height()
if scale_height:
height *= sx
self._image.resize(width, height, smooth)
return self._update_surface()
return self
[docs] def set_max_height(self, height: Optional[NumberType], scale_width: NumberType = False,
smooth: bool = True) -> 'Image':
if height is not None and self._image.get_height() > height:
sy = height / self._image.get_height()
width = self._image.get_width()
if scale_width:
width *= sy
self._image.resize(width, height, smooth)
return self._update_surface()
return self
[docs] def rotate(self, angle: NumberType) -> 'Image':
self._image.rotate(angle)
return self._update_surface()
[docs] def flip(self, x: bool, y: bool) -> 'Image':
assert isinstance(x, bool)
assert isinstance(y, bool)
self._flip = (x, y)
if x or y:
self._image.flip(x, y)
return self._update_surface()
return self
def _draw(self, surface: 'pygame.Surface') -> None:
surface.blit(self._surface, self._rect.topleft)
def _render(self) -> Optional[bool]:
if self._surface is not None:
return True
self._surface = self._image.get_surface(new=False)
self._rect.width, self._rect.height = self._surface.get_size()
if not self._render_hash_changed(self._visible):
return True
self.force_menu_surface_update()
def update(self, events: EventVectorType) -> bool:
self.apply_update_callbacks(events)
for event in events:
if self._check_mouseover(event):
break
return False