kvex.app
App and associated widgets.
To use the GUI, initialize and then run an XApp
:
app = XApp()
app.hook(func_to_call_every_frame, fps=20)
app.run()
1"""App and associated widgets. 2 3To use the GUI, initialize and then run an `XApp`: 4```python 5app = XApp() 6app.hook(func_to_call_every_frame, fps=20) 7app.run() 8``` 9""" 10from typing import Callable, Optional 11from contextlib import contextmanager 12from functools import partial 13from . import kivy as kv 14from .colors import XColor, THEMES, Theme 15from .util import ( 16 queue_around_frame, 17 restart_script, 18 consume_args, 19 schedule_interval, 20) 21from .behaviors import XFocusBehavior 22from .win_focus_patch import XWindowFocusPatch 23from .widgets.layouts import XAnchor, XAnchorDelayed 24from .widgets.label import XLabel 25 26 27DEFAULT_THEME_NAME = "mousefox" 28 29 30class XOverlay(XFocusBehavior, XAnchor): 31 """Overlay to be displayed on top of other widgets.""" 32 33 def __init__(self, **kwargs): 34 """Initialize like an XAnchor.""" 35 super().__init__() 36 self.make_bg(XColor(a=0.5)) 37 self.label = XLabel(**kwargs) 38 self.label.set_size(x=500, y=150) 39 self.label.make_bg(XColor.from_name("red", 0.15)) 40 self.add_widget(self.label) 41 42 43class XApp(kv.App): 44 """See module documentation for details.""" 45 46 current_focus = kv.ObjectProperty(None, allownone=True) 47 """Widget that currently has focus.""" 48 block_input = kv.BooleanProperty(False) 49 """If all user input should be blocked.""" 50 51 _theme_name: str = DEFAULT_THEME_NAME 52 _theme: Theme = THEMES[DEFAULT_THEME_NAME] 53 _subtheme_contexts: list[str] = [] 54 """List of subthemes for nested context. See `XApp.subtheme`.""" 55 56 window = kv.Window 57 """Kivy `Window`.""" 58 59 def __init__(self, escape_exits: bool = False, **kwargs): 60 """Initialize the class.""" 61 self.__window_focus_path = XWindowFocusPatch() 62 self.disable_multitouch() 63 self.enable_escape_exit(escape_exits) 64 super().__init__(**kwargs) 65 self.register_event_type("on_theme") 66 self.root = XAnchorDelayed() 67 self.keyboard = kv.Window.request_keyboard(consume_args, None) 68 self.__restart_flag = False 69 self.__overlay = None 70 schedule_interval(self._check_focus, 0) 71 kv.Window.bind( 72 on_touch_down=self._filter_touch, 73 on_touch_up=self._filter_touch, 74 on_touch_move=self._filter_touch, 75 ) 76 77 @property 78 def theme_name(self) -> str: 79 """Current theme name.""" 80 return self._theme_name 81 82 @property 83 def theme(self) -> Theme: 84 """Current `kvex.colors.Theme` object.""" 85 return self._theme 86 87 def set_theme(self, theme_name: str, /): 88 """Set the theme by name.""" 89 self._theme_name = theme_name 90 self._theme = THEMES[theme_name] 91 self.dispatch("on_theme", self._theme) 92 93 def on_theme(self, theme: Theme): 94 """Called when the theme has been set.""" 95 pass 96 97 @property 98 def subtheme_name(self) -> str: 99 """Current subtheme name, based on context from `XApp.subtheme_context`.""" 100 if not self._subtheme_contexts: 101 return "primary" 102 return self._subtheme_contexts[-1] 103 104 @contextmanager 105 def subtheme_context(self, subtheme: Optional[str]): 106 """Context manager for setting the subtheme. 107 108 While in context, all `kvex.behaviors.XThemed` widgets will default to this 109 subtheme. Subtheme contexts can be nested. For example: 110 111 ```python 112 with app.subtheme_context("secondary"): 113 XLabel(text="Secondary") 114 with app.subtheme_context("primary"): 115 XLabel(text="Primary") 116 with app.subtheme_context("accent"): 117 XLabel(text="Accent") 118 XLabel(text="Secondary") 119 ``` 120 """ 121 if subtheme: 122 context_index = len(self._subtheme_contexts) 123 self._subtheme_contexts.append(subtheme) 124 try: 125 yield 126 finally: 127 if subtheme: 128 # Remove our context and all further nested contexts from list 129 self._subtheme_contexts = self._subtheme_contexts[:context_index] 130 131 def _check_focus(self, *args): 132 self.current_focus = self.keyboard.target 133 134 def run(self, *args, allow_restart: bool = True, **kwargs) -> int: 135 """Run asyncronously. 136 137 The allow_restart argument determines what happens after using 138 `XApp.restart`. Will restart immediately if true, otherwise will 139 return -1. All other arguments are passed to the base method. 140 141 Returns 0 in all other cases. 142 """ 143 super().run(*args, **kwargs) 144 if allow_restart and self.__restart_flag: 145 restart_script() 146 return -1 if self.__restart_flag else 0 147 148 async def async_run(self, *args, allow_restart: bool = True, **kwargs) -> int: 149 """Run asyncronously. Arguments like `XApp.run`.""" 150 await super().async_run(*args, **kwargs) 151 if allow_restart and self.__restart_flag: 152 restart_script() 153 return -1 if self.__restart_flag else 0 154 155 def restart(self, *args): 156 """Restart the app by stopping `XApp.run` and returning -1.""" 157 self.__restart_flag = True 158 self.stop() 159 160 def hook(self, func: Callable[[float], None], fps: float): 161 """Schedule *func* to be called *fps* times per seconds.""" 162 kv.Clock.schedule_once(lambda *a: kv.Clock.schedule_interval(func, 1 / fps)) 163 164 def add_widget(self, *args, **kwargs): 165 """Add a widget to the root widget.""" 166 return self.root.add_widget(*args, **kwargs) 167 168 @property 169 def mouse_pos(self) -> tuple[float, float]: 170 """The current position of the mouse.""" 171 return kv.Window.mouse_pos 172 173 @staticmethod 174 def maximize(*args): 175 """Maixmize the window.""" 176 kv.Window.maximize() 177 178 @staticmethod 179 def set_size(x: float, y: float): 180 """Resize the window while maintaining it's center position.""" 181 oldx, oldy = kv.Window.size 182 top, left = kv.Window.top, kv.Window.left 183 bot, right = top + oldy, left + oldx 184 center = ((top + bot) / 2, (left + right) / 2) 185 center_offset = (y / 2, x / 2) 186 new_top_left = ( 187 int(center[0] - center_offset[0]), 188 int(center[1] - center_offset[1]), 189 ) 190 kv.Window.size = x, y 191 kv.Window.top, kv.Window.left = new_top_left 192 193 @staticmethod 194 def toggle_fullscreen(set_to: Optional[bool] = None): 195 """Toggle window fullscreen.""" 196 set_to = not kv.Window.fullscreen if set_to is None else set_to 197 kv.Window.fullscreen = set_to 198 199 @staticmethod 200 def toggle_borderless(set_to: Optional[bool] = None): 201 """Toggle window border.""" 202 set_to = not kv.Window.borderless if set_to is None else set_to 203 kv.Window.borderless = set_to 204 205 @staticmethod 206 def set_position(x: float, y: float): 207 """Reposition the window's top left position.""" 208 kv.Window.left, kv.Window.top = x, y 209 210 @staticmethod 211 def enable_escape_exit(set_to: bool = True): 212 """Toggles using the escape key to exit the program.""" 213 kv.Config.set("kivy", "exit_on_escape", str(int(set_to))) 214 215 @staticmethod 216 def disable_multitouch(): 217 """Toggles multitouch.""" 218 kv.Config.set("input", "mouse", "mouse,disable_multitouch") 219 220 @staticmethod 221 def enable_resize(set_to: bool): 222 """Toggles ability to resize the window.""" 223 kv.Config.set("graphics", "resizable", str(int(set_to))) 224 225 def open_settings(self, *args) -> False: 226 """Overrides base class method to disable the builtin settings widget.""" 227 return False 228 229 @property 230 def overlay(self) -> Optional[XOverlay]: 231 """The current overlay.""" 232 return self.__overlay 233 234 def with_overlay( 235 self, 236 func: Callable, 237 after: Optional[Callable] = None, 238 **kwargs, 239 ): 240 """Queue a function with a temporary `XOverlay` that blocks input. 241 242 Uses the `kvex.util.queue_around_frame` decorator to draw a frame before 243 calling the function, otherwise the added overlay will not be seen 244 until execution is yielded to kivy's clock. 245 246 Example usage: 247 ```python 248 with_overlay( 249 func=lambda: my_func(arg1=True), 250 text="my_func is executing...", 251 after=lambda: print("finished executing my_func."), 252 ) 253 ``` 254 255 Args: 256 func: Callback to queue after adding the overlay. 257 after: Optionally call after removing the overlay. 258 kwargs: Keyword arguments for the XOverlay object. 259 """ 260 if self.__overlay is not None: 261 raise RuntimeError("Cannot create an overlay when one already exists.") 262 queue_around_frame( 263 func, 264 before=partial(self.__create_overlay, **kwargs), 265 after=partial(self.__destroy_overlay, after), 266 )() 267 268 def _filter_touch(self, w, touch): 269 if self.block_input: 270 return True 271 if "button" not in touch.profile: 272 return True 273 return False 274 275 def __create_overlay(self, **kwargs): 276 self.__overlay = XOverlay(**kwargs) 277 self.__overlay.focus = True 278 self.block_input = True 279 self.add_widget(self.__overlay) 280 281 def __destroy_overlay(self, after: Optional[Callable] = None): 282 self.root.remove_widget(self.__overlay) 283 self.__overlay = None 284 self.block_input = False 285 if after is not None: 286 after() 287 288 289__all__ = ( 290 "XApp", 291)
44class XApp(kv.App): 45 """See module documentation for details.""" 46 47 current_focus = kv.ObjectProperty(None, allownone=True) 48 """Widget that currently has focus.""" 49 block_input = kv.BooleanProperty(False) 50 """If all user input should be blocked.""" 51 52 _theme_name: str = DEFAULT_THEME_NAME 53 _theme: Theme = THEMES[DEFAULT_THEME_NAME] 54 _subtheme_contexts: list[str] = [] 55 """List of subthemes for nested context. See `XApp.subtheme`.""" 56 57 window = kv.Window 58 """Kivy `Window`.""" 59 60 def __init__(self, escape_exits: bool = False, **kwargs): 61 """Initialize the class.""" 62 self.__window_focus_path = XWindowFocusPatch() 63 self.disable_multitouch() 64 self.enable_escape_exit(escape_exits) 65 super().__init__(**kwargs) 66 self.register_event_type("on_theme") 67 self.root = XAnchorDelayed() 68 self.keyboard = kv.Window.request_keyboard(consume_args, None) 69 self.__restart_flag = False 70 self.__overlay = None 71 schedule_interval(self._check_focus, 0) 72 kv.Window.bind( 73 on_touch_down=self._filter_touch, 74 on_touch_up=self._filter_touch, 75 on_touch_move=self._filter_touch, 76 ) 77 78 @property 79 def theme_name(self) -> str: 80 """Current theme name.""" 81 return self._theme_name 82 83 @property 84 def theme(self) -> Theme: 85 """Current `kvex.colors.Theme` object.""" 86 return self._theme 87 88 def set_theme(self, theme_name: str, /): 89 """Set the theme by name.""" 90 self._theme_name = theme_name 91 self._theme = THEMES[theme_name] 92 self.dispatch("on_theme", self._theme) 93 94 def on_theme(self, theme: Theme): 95 """Called when the theme has been set.""" 96 pass 97 98 @property 99 def subtheme_name(self) -> str: 100 """Current subtheme name, based on context from `XApp.subtheme_context`.""" 101 if not self._subtheme_contexts: 102 return "primary" 103 return self._subtheme_contexts[-1] 104 105 @contextmanager 106 def subtheme_context(self, subtheme: Optional[str]): 107 """Context manager for setting the subtheme. 108 109 While in context, all `kvex.behaviors.XThemed` widgets will default to this 110 subtheme. Subtheme contexts can be nested. For example: 111 112 ```python 113 with app.subtheme_context("secondary"): 114 XLabel(text="Secondary") 115 with app.subtheme_context("primary"): 116 XLabel(text="Primary") 117 with app.subtheme_context("accent"): 118 XLabel(text="Accent") 119 XLabel(text="Secondary") 120 ``` 121 """ 122 if subtheme: 123 context_index = len(self._subtheme_contexts) 124 self._subtheme_contexts.append(subtheme) 125 try: 126 yield 127 finally: 128 if subtheme: 129 # Remove our context and all further nested contexts from list 130 self._subtheme_contexts = self._subtheme_contexts[:context_index] 131 132 def _check_focus(self, *args): 133 self.current_focus = self.keyboard.target 134 135 def run(self, *args, allow_restart: bool = True, **kwargs) -> int: 136 """Run asyncronously. 137 138 The allow_restart argument determines what happens after using 139 `XApp.restart`. Will restart immediately if true, otherwise will 140 return -1. All other arguments are passed to the base method. 141 142 Returns 0 in all other cases. 143 """ 144 super().run(*args, **kwargs) 145 if allow_restart and self.__restart_flag: 146 restart_script() 147 return -1 if self.__restart_flag else 0 148 149 async def async_run(self, *args, allow_restart: bool = True, **kwargs) -> int: 150 """Run asyncronously. Arguments like `XApp.run`.""" 151 await super().async_run(*args, **kwargs) 152 if allow_restart and self.__restart_flag: 153 restart_script() 154 return -1 if self.__restart_flag else 0 155 156 def restart(self, *args): 157 """Restart the app by stopping `XApp.run` and returning -1.""" 158 self.__restart_flag = True 159 self.stop() 160 161 def hook(self, func: Callable[[float], None], fps: float): 162 """Schedule *func* to be called *fps* times per seconds.""" 163 kv.Clock.schedule_once(lambda *a: kv.Clock.schedule_interval(func, 1 / fps)) 164 165 def add_widget(self, *args, **kwargs): 166 """Add a widget to the root widget.""" 167 return self.root.add_widget(*args, **kwargs) 168 169 @property 170 def mouse_pos(self) -> tuple[float, float]: 171 """The current position of the mouse.""" 172 return kv.Window.mouse_pos 173 174 @staticmethod 175 def maximize(*args): 176 """Maixmize the window.""" 177 kv.Window.maximize() 178 179 @staticmethod 180 def set_size(x: float, y: float): 181 """Resize the window while maintaining it's center position.""" 182 oldx, oldy = kv.Window.size 183 top, left = kv.Window.top, kv.Window.left 184 bot, right = top + oldy, left + oldx 185 center = ((top + bot) / 2, (left + right) / 2) 186 center_offset = (y / 2, x / 2) 187 new_top_left = ( 188 int(center[0] - center_offset[0]), 189 int(center[1] - center_offset[1]), 190 ) 191 kv.Window.size = x, y 192 kv.Window.top, kv.Window.left = new_top_left 193 194 @staticmethod 195 def toggle_fullscreen(set_to: Optional[bool] = None): 196 """Toggle window fullscreen.""" 197 set_to = not kv.Window.fullscreen if set_to is None else set_to 198 kv.Window.fullscreen = set_to 199 200 @staticmethod 201 def toggle_borderless(set_to: Optional[bool] = None): 202 """Toggle window border.""" 203 set_to = not kv.Window.borderless if set_to is None else set_to 204 kv.Window.borderless = set_to 205 206 @staticmethod 207 def set_position(x: float, y: float): 208 """Reposition the window's top left position.""" 209 kv.Window.left, kv.Window.top = x, y 210 211 @staticmethod 212 def enable_escape_exit(set_to: bool = True): 213 """Toggles using the escape key to exit the program.""" 214 kv.Config.set("kivy", "exit_on_escape", str(int(set_to))) 215 216 @staticmethod 217 def disable_multitouch(): 218 """Toggles multitouch.""" 219 kv.Config.set("input", "mouse", "mouse,disable_multitouch") 220 221 @staticmethod 222 def enable_resize(set_to: bool): 223 """Toggles ability to resize the window.""" 224 kv.Config.set("graphics", "resizable", str(int(set_to))) 225 226 def open_settings(self, *args) -> False: 227 """Overrides base class method to disable the builtin settings widget.""" 228 return False 229 230 @property 231 def overlay(self) -> Optional[XOverlay]: 232 """The current overlay.""" 233 return self.__overlay 234 235 def with_overlay( 236 self, 237 func: Callable, 238 after: Optional[Callable] = None, 239 **kwargs, 240 ): 241 """Queue a function with a temporary `XOverlay` that blocks input. 242 243 Uses the `kvex.util.queue_around_frame` decorator to draw a frame before 244 calling the function, otherwise the added overlay will not be seen 245 until execution is yielded to kivy's clock. 246 247 Example usage: 248 ```python 249 with_overlay( 250 func=lambda: my_func(arg1=True), 251 text="my_func is executing...", 252 after=lambda: print("finished executing my_func."), 253 ) 254 ``` 255 256 Args: 257 func: Callback to queue after adding the overlay. 258 after: Optionally call after removing the overlay. 259 kwargs: Keyword arguments for the XOverlay object. 260 """ 261 if self.__overlay is not None: 262 raise RuntimeError("Cannot create an overlay when one already exists.") 263 queue_around_frame( 264 func, 265 before=partial(self.__create_overlay, **kwargs), 266 after=partial(self.__destroy_overlay, after), 267 )() 268 269 def _filter_touch(self, w, touch): 270 if self.block_input: 271 return True 272 if "button" not in touch.profile: 273 return True 274 return False 275 276 def __create_overlay(self, **kwargs): 277 self.__overlay = XOverlay(**kwargs) 278 self.__overlay.focus = True 279 self.block_input = True 280 self.add_widget(self.__overlay) 281 282 def __destroy_overlay(self, after: Optional[Callable] = None): 283 self.root.remove_widget(self.__overlay) 284 self.__overlay = None 285 self.block_input = False 286 if after is not None: 287 after()
See module documentation for details.
60 def __init__(self, escape_exits: bool = False, **kwargs): 61 """Initialize the class.""" 62 self.__window_focus_path = XWindowFocusPatch() 63 self.disable_multitouch() 64 self.enable_escape_exit(escape_exits) 65 super().__init__(**kwargs) 66 self.register_event_type("on_theme") 67 self.root = XAnchorDelayed() 68 self.keyboard = kv.Window.request_keyboard(consume_args, None) 69 self.__restart_flag = False 70 self.__overlay = None 71 schedule_interval(self._check_focus, 0) 72 kv.Window.bind( 73 on_touch_down=self._filter_touch, 74 on_touch_up=self._filter_touch, 75 on_touch_move=self._filter_touch, 76 )
Initialize the class.
88 def set_theme(self, theme_name: str, /): 89 """Set the theme by name.""" 90 self._theme_name = theme_name 91 self._theme = THEMES[theme_name] 92 self.dispatch("on_theme", self._theme)
Set the theme by name.
105 @contextmanager 106 def subtheme_context(self, subtheme: Optional[str]): 107 """Context manager for setting the subtheme. 108 109 While in context, all `kvex.behaviors.XThemed` widgets will default to this 110 subtheme. Subtheme contexts can be nested. For example: 111 112 ```python 113 with app.subtheme_context("secondary"): 114 XLabel(text="Secondary") 115 with app.subtheme_context("primary"): 116 XLabel(text="Primary") 117 with app.subtheme_context("accent"): 118 XLabel(text="Accent") 119 XLabel(text="Secondary") 120 ``` 121 """ 122 if subtheme: 123 context_index = len(self._subtheme_contexts) 124 self._subtheme_contexts.append(subtheme) 125 try: 126 yield 127 finally: 128 if subtheme: 129 # Remove our context and all further nested contexts from list 130 self._subtheme_contexts = self._subtheme_contexts[:context_index]
Context manager for setting the subtheme.
While in context, all kvex.behaviors.XThemed
widgets will default to this
subtheme. Subtheme contexts can be nested. For example:
with app.subtheme_context("secondary"):
XLabel(text="Secondary")
with app.subtheme_context("primary"):
XLabel(text="Primary")
with app.subtheme_context("accent"):
XLabel(text="Accent")
XLabel(text="Secondary")
135 def run(self, *args, allow_restart: bool = True, **kwargs) -> int: 136 """Run asyncronously. 137 138 The allow_restart argument determines what happens after using 139 `XApp.restart`. Will restart immediately if true, otherwise will 140 return -1. All other arguments are passed to the base method. 141 142 Returns 0 in all other cases. 143 """ 144 super().run(*args, **kwargs) 145 if allow_restart and self.__restart_flag: 146 restart_script() 147 return -1 if self.__restart_flag else 0
Run asyncronously.
The allow_restart argument determines what happens after using
XApp.restart
. Will restart immediately if true, otherwise will
return -1. All other arguments are passed to the base method.
Returns 0 in all other cases.
149 async def async_run(self, *args, allow_restart: bool = True, **kwargs) -> int: 150 """Run asyncronously. Arguments like `XApp.run`.""" 151 await super().async_run(*args, **kwargs) 152 if allow_restart and self.__restart_flag: 153 restart_script() 154 return -1 if self.__restart_flag else 0
Run asyncronously. Arguments like XApp.run
.
156 def restart(self, *args): 157 """Restart the app by stopping `XApp.run` and returning -1.""" 158 self.__restart_flag = True 159 self.stop()
Restart the app by stopping XApp.run
and returning -1.
161 def hook(self, func: Callable[[float], None], fps: float): 162 """Schedule *func* to be called *fps* times per seconds.""" 163 kv.Clock.schedule_once(lambda *a: kv.Clock.schedule_interval(func, 1 / fps))
Schedule func to be called fps times per seconds.
165 def add_widget(self, *args, **kwargs): 166 """Add a widget to the root widget.""" 167 return self.root.add_widget(*args, **kwargs)
Add a widget to the root widget.
179 @staticmethod 180 def set_size(x: float, y: float): 181 """Resize the window while maintaining it's center position.""" 182 oldx, oldy = kv.Window.size 183 top, left = kv.Window.top, kv.Window.left 184 bot, right = top + oldy, left + oldx 185 center = ((top + bot) / 2, (left + right) / 2) 186 center_offset = (y / 2, x / 2) 187 new_top_left = ( 188 int(center[0] - center_offset[0]), 189 int(center[1] - center_offset[1]), 190 ) 191 kv.Window.size = x, y 192 kv.Window.top, kv.Window.left = new_top_left
Resize the window while maintaining it's center position.
194 @staticmethod 195 def toggle_fullscreen(set_to: Optional[bool] = None): 196 """Toggle window fullscreen.""" 197 set_to = not kv.Window.fullscreen if set_to is None else set_to 198 kv.Window.fullscreen = set_to
Toggle window fullscreen.
200 @staticmethod 201 def toggle_borderless(set_to: Optional[bool] = None): 202 """Toggle window border.""" 203 set_to = not kv.Window.borderless if set_to is None else set_to 204 kv.Window.borderless = set_to
Toggle window border.
206 @staticmethod 207 def set_position(x: float, y: float): 208 """Reposition the window's top left position.""" 209 kv.Window.left, kv.Window.top = x, y
Reposition the window's top left position.
211 @staticmethod 212 def enable_escape_exit(set_to: bool = True): 213 """Toggles using the escape key to exit the program.""" 214 kv.Config.set("kivy", "exit_on_escape", str(int(set_to)))
Toggles using the escape key to exit the program.
216 @staticmethod 217 def disable_multitouch(): 218 """Toggles multitouch.""" 219 kv.Config.set("input", "mouse", "mouse,disable_multitouch")
Toggles multitouch.
221 @staticmethod 222 def enable_resize(set_to: bool): 223 """Toggles ability to resize the window.""" 224 kv.Config.set("graphics", "resizable", str(int(set_to)))
Toggles ability to resize the window.
226 def open_settings(self, *args) -> False: 227 """Overrides base class method to disable the builtin settings widget.""" 228 return False
Overrides base class method to disable the builtin settings widget.
235 def with_overlay( 236 self, 237 func: Callable, 238 after: Optional[Callable] = None, 239 **kwargs, 240 ): 241 """Queue a function with a temporary `XOverlay` that blocks input. 242 243 Uses the `kvex.util.queue_around_frame` decorator to draw a frame before 244 calling the function, otherwise the added overlay will not be seen 245 until execution is yielded to kivy's clock. 246 247 Example usage: 248 ```python 249 with_overlay( 250 func=lambda: my_func(arg1=True), 251 text="my_func is executing...", 252 after=lambda: print("finished executing my_func."), 253 ) 254 ``` 255 256 Args: 257 func: Callback to queue after adding the overlay. 258 after: Optionally call after removing the overlay. 259 kwargs: Keyword arguments for the XOverlay object. 260 """ 261 if self.__overlay is not None: 262 raise RuntimeError("Cannot create an overlay when one already exists.") 263 queue_around_frame( 264 func, 265 before=partial(self.__create_overlay, **kwargs), 266 after=partial(self.__destroy_overlay, after), 267 )()
Queue a function with a temporary XOverlay
that blocks input.
Uses the kvex.util.queue_around_frame
decorator to draw a frame before
calling the function, otherwise the added overlay will not be seen
until execution is yielded to kivy's clock.
Example usage:
with_overlay(
func=lambda: my_func(arg1=True),
text="my_func is executing...",
after=lambda: print("finished executing my_func."),
)
Arguments:
- func: Callback to queue after adding the overlay.
- after: Optionally call after removing the overlay.
- kwargs: Keyword arguments for the XOverlay object.
Inherited Members
- kivy.app.App
- title
- icon
- use_kivy_settings
- settings_cls
- kv_directory
- kv_file
- build
- build_config
- build_settings
- load_kv
- get_application_name
- get_application_icon
- get_application_config
- root_window
- load_config
- directory
- user_data_dir
- name
- stop
- on_start
- on_stop
- on_pause
- on_resume
- get_running_app
- on_config_change
- display_settings
- close_settings
- create_settings
- destroy_settings
- on_title
- on_icon
- kivy._event.EventDispatcher
- register_event_type
- unregister_event_types
- unregister_event_type
- is_event_type
- bind
- unbind
- fbind
- funbind
- unbind_uid
- get_property_observers
- events
- dispatch
- dispatch_generic
- dispatch_children
- setter
- getter
- property
- properties
- create_property
- apply_property
- proxy_ref