From c767ebf6b9ae6e544fe2bebbde3b653c8278e801 Mon Sep 17 00:00:00 2001 From: Peter Hinch Date: Sun, 23 Mar 2025 12:49:50 +0000 Subject: [PATCH] Provide for splash screens. --- README.md | 6 +++++- gui/core/ugui.py | 12 +++++------ gui/demos/screen_change.py | 41 ++++++++++++++++++++++++++++---------- 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 706c826..6c0b63d 100644 --- a/README.md +++ b/README.md @@ -1036,7 +1036,11 @@ See `demos/plot.py` for an example of multi-screen design, or ## 4.2 Constructor -This takes no arguments. +This takes one optional argument. + * `writer=None` In general a `Screen` must have at least on active widget. In + the special case where there are none (e.g. a splash screen), a `Writer` + instance should be passed. Application code should close the splash screen by + issuing `Screen.back()`. ## 4.3 Callback methods diff --git a/gui/core/ugui.py b/gui/core/ugui.py index 75f84ec..3576672 100644 --- a/gui/core/ugui.py +++ b/gui/core/ugui.py @@ -477,7 +477,7 @@ class Screen: def shutdown(cls): cls.is_shutdown.set() # Tell monitor() to shutdown - def __init__(self): + def __init__(self, writer=None): self.lstactive = [] # Controls which respond to Select button self.selected_obj = None # Index of currently selected object self.displaylist = [] # All displayable objects @@ -491,6 +491,8 @@ class Screen: asyncio.create_task(self._garbage_collect()) Screen.current_screen = self self.parent = None + if writer is not None: # Special case of no active widgets (e.g. popup message) + DummyWidget(writer, self) # Invisible active widget def _do_open(self, old_screen): # Window overrides dev = display.usegrey(False) @@ -621,7 +623,7 @@ class Window(Screen): fgcolor=None, writer=None, ): - Screen.__init__(self) + Screen.__init__(self, writer) self.row = row self.col = col self.height = height @@ -629,8 +631,6 @@ class Window(Screen): self.draw_border = draw_border self.fgcolor = fgcolor if fgcolor is not None else color_map[FG] self.bgcolor = bgcolor if bgcolor is not None else color_map[BG] - if writer is not None: # Special case of popup message - DummyWidget(writer, self) # Invisible active widget def _do_open(self, old_screen): dev = display.usegrey(False) @@ -898,8 +898,8 @@ class DummyWidget(Widget): window.col + 1, 4, 4, - window.fgcolor, - window.bgcolor, + None, + None, False, None, True, diff --git a/gui/demos/screen_change.py b/gui/demos/screen_change.py index ba82150..01f2fe4 100644 --- a/gui/demos/screen_change.py +++ b/gui/demos/screen_change.py @@ -1,7 +1,7 @@ # screen_change.py Minimal micro-gui demo showing a Button causing a screen change. # Released under the MIT License (MIT). See LICENSE. -# Copyright (c) 2021 Peter Hinch +# Copyright (c) 2021-2025 Peter Hinch # hardware_setup must be imported before other modules because of RAM use. import hardware_setup # Create a display instance @@ -13,41 +13,62 @@ from gui.core.writer import CWriter # Font for CWriter import gui.fonts.arial10 as font from gui.core.colors import * +import asyncio +import time # Defining a button in this way enables it to be re-used on # multiple Screen instances. Note that a Screen class is # passed, not an instance. -def fwdbutton(wri, row, col, cls_screen, text='Next'): +def fwdbutton(wri, row, col, cls_screen, text="Next"): def fwd(button): Screen.change(cls_screen) # Callback - Button(wri, row, col, callback = fwd, - fgcolor = BLACK, bgcolor = GREEN, - text = text, shape = RECTANGLE) + Button(wri, row, col, callback=fwd, fgcolor=BLACK, bgcolor=GREEN, text=text, shape=RECTANGLE) + wri = CWriter(ssd, font, GREEN, BLACK, verbose=False) # This screen overlays BaseScreen. class BackScreen(Screen): - def __init__(self): super().__init__() - Label(wri, 2, 2, 'New screen.') + Label(wri, 2, 2, "New screen.") CloseButton(wri) +# The splash screen is a special case of a Screen with no active widgets. +class SplashScreen(Screen): + def __init__(self): + super().__init__(wri) # No sctive widgets: must pass writer + Label(wri, 10, 10, "Splash screen") + Label(wri, 40, 10, "Please wait", fgcolor=YELLOW) + + def after_open(self): # Cle after a period + asyncio.create_task(self.close_me()) + + async def close_me(self): + await asyncio.sleep(3) + Screen.back() + + class BaseScreen(Screen): - def __init__(self): super().__init__() - Label(wri, 2, 2, 'Base screen.') + Label(wri, 2, 2, "Base screen.") fwdbutton(wri, 40, 2, BackScreen) CloseButton(wri) + self.splash_done = False + + def after_open(self): + if not self.splash_done: # Only show splash on initial opening. + Screen.change(SplashScreen) + self.splash_done = True def test(): - print('Screen change demo.') + print("Screen change demo.") Screen.change(BaseScreen) # Pass class, not instance! + test()