[MouseFox logo]
The MouseFox Project
Join The Community Discord Server
[Discord logo]
Edit on GitHub

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)
class XApp(kivy.app.App):
 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.

XApp(escape_exits: bool = False, **kwargs)
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.

current_focus

Widget that currently has focus.

block_input

If all user input should be blocked.

window = <kivy.core.window.window_sdl2.WindowSDL object>

Kivy Window.

theme_name: str

Current theme name.

Current kvex.colors.Theme object.

def set_theme(self, theme_name: str, /):
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.

def on_theme(self, theme: kvex.colors.Theme):
94    def on_theme(self, theme: Theme):
95        """Called when the theme has been set."""
96        pass

Called when the theme has been set.

subtheme_name: str

Current subtheme name, based on context from XApp.subtheme_context.

@contextmanager
def subtheme_context(self, subtheme: Optional[str]):
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")
def run(self, *args, allow_restart: bool = True, **kwargs) -> int:
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.

async def async_run(self, *args, allow_restart: bool = True, **kwargs) -> int:
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.

def restart(self, *args):
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.

def hook(self, func: Callable[[float], NoneType], fps: float):
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.

def add_widget(self, *args, **kwargs):
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.

mouse_pos: tuple[float, float]

The current position of the mouse.

@staticmethod
def maximize(*args):
174    @staticmethod
175    def maximize(*args):
176        """Maixmize the window."""
177        kv.Window.maximize()

Maixmize the window.

@staticmethod
def set_size(x: float, y: float):
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.

@staticmethod
def toggle_fullscreen(set_to: Optional[bool] = None):
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.

@staticmethod
def toggle_borderless(set_to: Optional[bool] = None):
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.

@staticmethod
def set_position(x: float, y: float):
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.

@staticmethod
def enable_escape_exit(set_to: bool = True):
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.

@staticmethod
def disable_multitouch():
216    @staticmethod
217    def disable_multitouch():
218        """Toggles multitouch."""
219        kv.Config.set("input", "mouse", "mouse,disable_multitouch")

Toggles multitouch.

@staticmethod
def enable_resize(set_to: bool):
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.

def open_settings(self, *args) -> False:
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.

overlay: Optional[kvex.app.XOverlay]

The current overlay.

def with_overlay(self, func: Callable, after: Optional[Callable] = None, **kwargs):
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