Skip to content

Commit ed44bf1

Browse files
authored
Merge pull request #440 from ppizarror/menu-render-disable-enable
Menu render disable/enable
2 parents a2b4228 + 7d51677 commit ed44bf1

File tree

3 files changed

+96
-1
lines changed

3 files changed

+96
-1
lines changed

pygame_menu/menu.py

+50
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ def __init__(
362362
self._last_selected_type = '' # Last type selection, used for test purposes
363363
self._mainloop = False # Menu is in mainloop state
364364
self._onclose = None # Function or event called on Menu close
365+
self._render_enabled = True
365366
self._sound = Sound()
366367
self._stats = _MenuStats()
367368
self._submenus = {}
@@ -1952,6 +1953,8 @@ def _render(self) -> bool:
19521953
19531954
:return: ``True`` if the surface has changed (if it was ``None``)
19541955
"""
1956+
if not self._render_enabled:
1957+
return False # Modify using Menu.disable_render() and Menu.enable_render()
19551958
t0 = time.time()
19561959
changed = False
19571960

@@ -1969,6 +1972,39 @@ def _render(self) -> bool:
19691972
self._stats.total_rendering_time += time.time() - t0
19701973
return changed
19711974

1975+
def disable_render(self) -> 'Menu':
1976+
"""
1977+
Disable the render of the Menu. Useful to improve performance when
1978+
adding many widgets. Must be turned on after finishing the build.
1979+
1980+
.. note::
1981+
1982+
This is applied only to the base Menu (not the currently displayed,
1983+
stored in ``_current`` pointer); for such behaviour apply to
1984+
:py:meth:`pygame_menu.menu.Menu.get_current` object.
1985+
1986+
:return: Self reference
1987+
"""
1988+
self._render_enabled = False
1989+
return self
1990+
1991+
def enable_render(self) -> 'Menu':
1992+
"""
1993+
Enable the Menu rendering. Useful to improve performance when
1994+
adding many widgets.
1995+
1996+
.. note::
1997+
1998+
This is applied only to the base Menu (not the currently displayed,
1999+
stored in ``_current`` pointer); for such behaviour apply to
2000+
:py:meth:`pygame_menu.menu.Menu.get_current` object.
2001+
2002+
:return: Self reference
2003+
"""
2004+
self._render_enabled = True
2005+
self._render()
2006+
return self
2007+
19722008
def draw(self, surface: 'pygame.Surface', clear_surface: bool = False) -> 'Menu':
19732009
"""
19742010
Draw the **current** Menu into the given surface.
@@ -3380,6 +3416,20 @@ def get_window_size(self) -> Tuple2IntType:
33803416
"""
33813417
return self._window_size
33823418

3419+
def get_col_rows(self) -> Tuple[int, List[int]]:
3420+
"""
3421+
Return the number of columns and rows of the Menu.
3422+
3423+
.. note::
3424+
3425+
This is applied only to the base Menu (not the currently displayed,
3426+
stored in ``_current`` pointer); for such behaviour apply to
3427+
:py:meth:`pygame_menu.menu.Menu.get_current` object.
3428+
3429+
:return: Tuple of (columns, rows for each column)
3430+
"""
3431+
return self._columns, self._rows
3432+
33833433
def get_submenus(self, recursive: bool = False) -> Tuple['Menu', ...]:
33843434
"""
33853435
Return the Menu submenus as a tuple.

pygame_menu/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@ def __str__(self) -> str:
3434
patch = property(lambda self: self[2])
3535

3636

37-
vernum = Version(4, 3, 3)
37+
vernum = Version(4, 3, 4)
3838
ver = str(vernum)
3939
rev = ''

test/test_menu.py

+45
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
from typing import Any, Tuple, List
1515
import copy
1616
import math
17+
import sys
18+
import time
1719
import timeit
1820

1921
import pygame
@@ -1232,6 +1234,9 @@ def test_columns_menu(self) -> None:
12321234
menu.render()
12331235
self.assertEqual(menu._column_widths, [200, 150, 150])
12341236

1237+
menu = MenuUtils.generic_menu()
1238+
self.assertEqual(menu.get_col_rows(), (1, [10000000]))
1239+
12351240
def test_screen_dimension(self) -> None:
12361241
"""
12371242
Test screen dim.
@@ -2217,6 +2222,8 @@ def test_baseimage_selector(self) -> None:
22172222
"""
22182223
Test baseimage selector + menulink interaction.
22192224
"""
2225+
if sys.version_info.major == 3 and sys.version_info.minor == 8:
2226+
return
22202227
x = 400
22212228
y = 400
22222229

@@ -2471,3 +2478,41 @@ def test_border_color(self) -> None:
24712478
theme.border_color = pygame_menu.BaseImage(pygame_menu.baseimage.IMAGE_EXAMPLE_TILED_BORDER)
24722479
menu = pygame_menu.Menu('Menu with border image', 250, 250, theme=theme)
24732480
menu.draw(surface)
2481+
2482+
def test_menu_render_toggle(self) -> None:
2483+
"""
2484+
Test add menu widgets with render enable/disable.
2485+
"""
2486+
menu = MenuUtils.generic_menu(columns=3, rows=50)
2487+
nc, nr = menu.get_col_rows()
2488+
self.assertEqual(nc, 3)
2489+
self.assertEqual(nr, [50, 50, 50])
2490+
2491+
# Test with rendering enabled
2492+
n = sum(nr) # Number of widgets to be added
2493+
t0 = time.time()
2494+
widgets: List[Label] = []
2495+
for i in range(n):
2496+
widgets.append(menu.add.label(i))
2497+
t_on = time.time() - t0
2498+
position_before: List[Tuple[int, int]] = []
2499+
for i in range(n):
2500+
position_before.append(widgets[i].get_position())
2501+
2502+
# Test with rendering disabled
2503+
menu.clear()
2504+
widgets.clear()
2505+
menu.disable_render()
2506+
t0 = time.time()
2507+
for i in range(n):
2508+
widgets.append(menu.add.label(i))
2509+
menu.enable_render()
2510+
menu.render()
2511+
t_off = time.time() - t0
2512+
self.assertGreater(t_on, t_off)
2513+
2514+
# Position after render must be equal!
2515+
for i in range(n):
2516+
self.assertEqual(position_before[i], widgets[i].get_position())
2517+
2518+
print(f'Render on: {t_on}s, off: {t_off}s')

0 commit comments

Comments
 (0)