slint

Slint-python (Beta)

Slint is a UI toolkit that supports different programming languages. Slint-python is the integration with Python.

Warning Slint-python is in a beta phase of development: The APIs while mostly stable, may be subject to further changes. Any changes will be documented in the ChangeLog.

You can track the progress for the Python integration by looking at python-labelled issues at https://github.com/slint-ui/slint/labels/a%3Alanguage-python .

Slint Language Manual

The Slint Language Documentation covers the Slint UI description language in detail.

Prerequisites

Installation

Install Slint with uv or pip from the Python Package Index:

uv add slint

The installation uses binaries provided for macOS, Windows, and Linux for various architectures. If your target platform is not covered by binaries, uv will automatically build Slint from source. If that happens, you will then need some software development tools on your machine, as well as Rust.

Quick Start

  1. Create a new project with uv init.
  2. Add the Slint Python package to your Python project: uv add slint
  3. Create a file called app-window.slint:
import { Button, VerticalBox } from "std-widgets.slint";

export component AppWindow inherits Window {
    in-out property<int> counter: 42;
    callback request-increase-value();
    VerticalBox {
        Text {
            text: "Counter: \{root.counter}";
        }
        Button {
            text: "Increase value";
            clicked => {
                root.request-increase-value();
            }
        }
    }
}
  1. Create a file called main.py:
import slint

# slint.loader will look in `sys.path` for `app-window.slint`.
class App(slint.loader.app_window.AppWindow):
    @slint.callback
    def request_increase_value(self):
        self.counter = self.counter + 1

app = App()
app.run()
  1. Run it with uv run main.py

API Overview

Instantiating a Component

The following example shows how to instantiate a Slint component in Python:

app.slint

export component MainWindow inherits Window {
    callback clicked <=> i-touch-area.clicked;

    in property <int> counter;

    width: 400px;
    height: 200px;

    i-touch-area := TouchArea {}
}

The exported component is exposed as a Python class. To access this class, you have two options:

  1. Call slint.load_file("app.slint"). The returned object is a namespace, that provides the MainWindow class as well as any other explicitly exported component that inherits Window:

    import slint
    components = slint.load_file("app.slint")
    main_window = components.MainWindow()
    
  2. Use Slint's auto-loader, which lazily loads .slint files from sys.path:

    import slint
    # Look for for `app.slint` in `sys.path`:
    main_window = slint.loader.app.MainWindow()
    

    Any attribute lookup in slint.loader is searched for in sys.path. If a directory with the name exists, it is returned as a loader object, and subsequent attribute lookups follow the same logic.

    If the name matches a file with the .slint extension, it is automatically loaded with load_file and the namespace is returned.

    If the file name contains a dash, like app-window.slint, an attribute lookup for app_window tries to locate app_window.slint and then fall back to app-window.slint.

Accessing Properties

Properties declared as out or in-out in .slint files are visible as properties on the component instance.

main_window.counter = 42
print(main_window.counter)

Accessing Globals

Global Singletons are accessible in Python as properties in the component instance.

For example, this Slint code declares a PrinterJobQueue singleton:

export global PrinterJobQueue {
    in-out property <int> job-count;
}

Access it as a property on the component instance by its name:

print("job count:", instance.PrinterJobQueue.job_count)

Note: Global singletons are instantiated once per component. When declaring multiple components for export to Python, each instance has their own associated globals singletons.

Setting and Invoking Callbacks

Callbacks declared in .slint files are visible as callable properties on the component instance. Invoke them as functions to invoke the callback, and assign Python callables to set the callback handler.

In Slint, callbacks are defined using the callback keyword and can be connected to another component's callback using the <=> syntax.

my-component.slint

export component MyComponent inherits Window {
    callback clicked <=> i-touch-area.clicked;

    width: 400px;
    height: 200px;

    i-touch-area := TouchArea {}
}

The callbacks in Slint are exposed as properties and that can be called as functions.

main.py

import slint

component = slint.loader.my_component.MyComponent()
# connect to a callback

def clicked():
    print("hello")

component.clicked = clicked
// invoke a callback
component.clicked();

Another way to set callbacks is to sub-class and use the @slint.callback decorator:

import slint

class Component(slint.loader.my_component.MyComponent):
    @slint.callback
    def clicked(self):
        print("hello")

component = Component()

The @slint.callback() decorator accepts a name argument, if the name of the method does not match the name of the callback in the .slint file. Similarly, a global_name argument can be used to bind a method to a callback in a global singleton.

Type Mappings

Each type used for properties in the Slint Language translates to a specific type in Python. The following table summarizes the mapping:

.slint Type Python Type Notes
int int
float float
string str
color slint.Color
brush slint.Brush
image slint.Image
length float
physical_length float
duration float The number of milliseconds
angle float The angle in degrees
structure dict/Struct When reading, structures are mapped to data classes, when writing dicts are also accepted.
array slint.Model

Arrays and Models

You can set array properties from Python by passing subclasses of slint.Model.

Use the slint.ListModel class to construct a model from an iterable:

component.model = slint.ListModel([1, 2, 3]);
component.model.append(4)
del component.model[0]

When sub-classing slint.Model, provide the following methods:

    def row_count(self):
        """Return the number of rows in your model"""

    def row_data(self, row):
        """Return data at specified row"""

    def set_row_data(self, row, data):
        """For read-write models, store data in the given row. When done call set.notify_row_changed:"
        ..."""
        self.notify_row_changed(row)

When adding or inserting rows, call notify_row_added(row, count) on the super class. Similarly, when removing rows, notify Slint by calling notify_row_removed(row, count).

Structs

Structs declared in Slint and exposed to Python via export are then accessible in the namespace that is returned when instantiating a component.

app.slint

export struct MyData {
    name: string,
    age: int
}

export component MainWindow inherits Window {
    in-out property <MyData> data;
}

main.py

The exported MyData struct can be constructed as follows:

import slint
# Look for for `app.slint` in `sys.path`:
main_window = slint.loader.app.MainWindow()

data = slint.loader.app.MyData(name = "Simon")
data.age = 10
main_window.data = data

Enums

Enums declared in Slint and exposed to Python via export are then accessible in the namespace that is returned when instantiating a component. The enums are subclasses of enum.Enum.

app.slint

export enum MyOption {
    Variant1,
    Variant2
}

export component MainWindow inherits Window {
    in-out property <MyOption> data;
}

main.py

Variants of the exported MyOption enum can be constructed as follows:

import slint
# Look for for `app.slint` in `sys.path`:
main_window = slint.loader.app.MainWindow()

value = slint.loader.app.MyOption.Variant2
main_window.data = value

Asynchronous I/O

Use Python's asyncio library to write concurrent Python code with the async/await syntax.

Slint's event loop is a full-featured asyncio event loop. While the event loop is running, asyncio.get_event_loop() returns a valid loop. To run an async function when starting the loop, pass a coroutine to slint.run_event_loop().

For the common use case of interacting with REST APIs, we recommend the aiohttp library.

Known Limitations

  • Pipes and sub-processes are only supported on Unix-like platforms.

Third-Party Licenses

For a list of the third-party licenses of all dependencies, see the separate Third-Party Licenses page.

  1# Copyright © SixtyFPS GmbH <[email protected]>
  2# SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
  3
  4r"""
  5.. include:: ../README.md
  6"""
  7
  8import os
  9import sys
 10from . import slint as native
 11import types
 12import logging
 13import copy
 14import typing
 15from typing import Any
 16import pathlib
 17from .models import ListModel, Model
 18from .slint import Image, Color, Brush, Timer, TimerMode
 19from .loop import SlintEventLoop
 20from pathlib import Path
 21from collections.abc import Coroutine
 22import asyncio
 23import gettext
 24
 25Struct = native.PyStruct
 26
 27
 28class CompileError(Exception):
 29    message: str
 30    """The error message that produced this compile error."""
 31
 32    diagnostics: list[native.PyDiagnostic]
 33    """A list of detailed diagnostics that were produced as part of the compilation."""
 34
 35    def __init__(self, message: str, diagnostics: list[native.PyDiagnostic]):
 36        """@private"""
 37        super().__init__(message)
 38        self.message = message
 39        self.diagnostics = diagnostics
 40        for diag in self.diagnostics:
 41            self.add_note(str(diag))
 42
 43
 44class Component:
 45    """Component is the base class for all instances of Slint components. Use the member functions to show or hide the
 46    window, or spin the event loop."""
 47
 48    __instance__: native.ComponentInstance
 49
 50    def show(self) -> None:
 51        """Shows the window on the screen."""
 52
 53        self.__instance__.show()
 54
 55    def hide(self) -> None:
 56        """Hides the window from the screen."""
 57
 58        self.__instance__.hide()
 59
 60    def run(self) -> None:
 61        """Shows the window, runs the event loop, hides it when the loop is quit, and returns."""
 62        self.show()
 63        run_event_loop()
 64        self.hide()
 65
 66
 67def _normalize_prop(name: str) -> str:
 68    return name.replace("-", "_")
 69
 70
 71def _build_global_class(compdef: native.ComponentDefinition, global_name: str) -> Any:
 72    properties_and_callbacks = {}
 73
 74    for prop_name in compdef.global_properties(global_name).keys():
 75        python_prop = _normalize_prop(prop_name)
 76        if python_prop in properties_and_callbacks:
 77            logging.warning(f"Duplicated property {prop_name}")
 78            continue
 79
 80        def mk_setter_getter(prop_or_callback_name: str) -> property:
 81            def getter(self: Component) -> Any:
 82                return self.__instance__.get_global_property(
 83                    global_name, prop_or_callback_name
 84                )
 85
 86            def setter(self: Component, value: Any) -> None:
 87                self.__instance__.set_global_property(
 88                    global_name, prop_or_callback_name, value
 89                )
 90
 91            return property(getter, setter)
 92
 93        properties_and_callbacks[python_prop] = mk_setter_getter(prop_name)
 94
 95    for callback_name in compdef.global_callbacks(global_name):
 96        python_prop = _normalize_prop(callback_name)
 97        if python_prop in properties_and_callbacks:
 98            logging.warning(f"Duplicated property {prop_name}")
 99            continue
100
101        def mk_setter_getter(prop_or_callback_name: str) -> property:
102            def getter(self: Component) -> typing.Callable[..., Any]:
103                def call(*args: Any) -> Any:
104                    return self.__instance__.invoke_global(
105                        global_name, prop_or_callback_name, *args
106                    )
107
108                return call
109
110            def setter(self: Component, value: typing.Callable[..., Any]) -> None:
111                self.__instance__.set_global_callback(
112                    global_name, prop_or_callback_name, value
113                )
114
115            return property(getter, setter)
116
117        properties_and_callbacks[python_prop] = mk_setter_getter(callback_name)
118
119    for function_name in compdef.global_functions(global_name):
120        python_prop = _normalize_prop(function_name)
121        if python_prop in properties_and_callbacks:
122            logging.warning(f"Duplicated function {prop_name}")
123            continue
124
125        def mk_getter(function_name: str) -> property:
126            def getter(self: Component) -> typing.Callable[..., Any]:
127                def call(*args: Any) -> Any:
128                    return self.__instance__.invoke_global(
129                        global_name, function_name, *args
130                    )
131
132                return call
133
134            return property(getter)
135
136        properties_and_callbacks[python_prop] = mk_getter(function_name)
137
138    return type("SlintGlobalClassWrapper", (), properties_and_callbacks)
139
140
141def _build_class(
142    compdef: native.ComponentDefinition,
143) -> typing.Callable[..., Component]:
144    def cls_init(self: Component, **kwargs: Any) -> Any:
145        self.__instance__ = compdef.create()
146        for name, value in self.__class__.__dict__.items():
147            if hasattr(value, "slint.callback"):
148                callback_info = getattr(value, "slint.callback")
149                name = callback_info["name"]
150
151                is_async = getattr(value, "slint.async", False)
152                if is_async:
153                    if "global_name" in callback_info:
154                        global_name = callback_info["global_name"]
155                        if not compdef.global_callback_returns_void(global_name, name):
156                            raise RuntimeError(
157                                f"Callback '{name}' in global '{global_name}' cannot be used with a callback decorator for an async function, as it doesn't return void"
158                            )
159                    else:
160                        if not compdef.callback_returns_void(name):
161                            raise RuntimeError(
162                                f"Callback '{name}' cannot be used with a callback decorator for an async function, as it doesn't return void"
163                            )
164
165                def mk_callback(
166                    self: Any, callback: typing.Callable[..., Any]
167                ) -> typing.Callable[..., Any]:
168                    def invoke(*args: Any, **kwargs: Any) -> Any:
169                        return callback(self, *args, **kwargs)
170
171                    return invoke
172
173                if "global_name" in callback_info:
174                    self.__instance__.set_global_callback(
175                        callback_info["global_name"], name, mk_callback(self, value)
176                    )
177                else:
178                    self.__instance__.set_callback(name, mk_callback(self, value))
179
180        for prop, val in kwargs.items():
181            setattr(self, prop, val)
182
183    properties_and_callbacks: dict[Any, Any] = {"__init__": cls_init}
184
185    for prop_name in compdef.properties.keys():
186        python_prop = _normalize_prop(prop_name)
187        if python_prop in properties_and_callbacks:
188            logging.warning(f"Duplicated property {prop_name}")
189            continue
190
191        def mk_setter_getter(prop_or_callback_name: str) -> property:
192            def getter(self: Component) -> Any:
193                return self.__instance__.get_property(prop_or_callback_name)
194
195            def setter(self: Component, value: Any) -> None:
196                self.__instance__.set_property(prop_or_callback_name, value)
197
198            return property(getter, setter)
199
200        properties_and_callbacks[python_prop] = mk_setter_getter(prop_name)
201
202    for callback_name in compdef.callbacks:
203        python_prop = _normalize_prop(callback_name)
204        if python_prop in properties_and_callbacks:
205            logging.warning(f"Duplicated property {prop_name}")
206            continue
207
208        def mk_setter_getter(prop_or_callback_name: str) -> property:
209            def getter(self: Component) -> typing.Callable[..., Any]:
210                def call(*args: Any) -> Any:
211                    return self.__instance__.invoke(prop_or_callback_name, *args)
212
213                return call
214
215            def setter(self: Component, value: typing.Callable[..., Any]) -> None:
216                self.__instance__.set_callback(prop_or_callback_name, value)
217
218            return property(getter, setter)
219
220        properties_and_callbacks[python_prop] = mk_setter_getter(callback_name)
221
222    for function_name in compdef.functions:
223        python_prop = _normalize_prop(function_name)
224        if python_prop in properties_and_callbacks:
225            logging.warning(f"Duplicated function {prop_name}")
226            continue
227
228        def mk_getter(function_name: str) -> property:
229            def getter(self: Component) -> typing.Callable[..., Any]:
230                def call(*args: Any) -> Any:
231                    return self.__instance__.invoke(function_name, *args)
232
233                return call
234
235            return property(getter)
236
237        properties_and_callbacks[python_prop] = mk_getter(function_name)
238
239    for global_name in compdef.globals:
240        global_class = _build_global_class(compdef, global_name)
241
242        def mk_global(global_class: typing.Callable[..., Any]) -> property:
243            def global_getter(self: Component) -> Any:
244                wrapper = global_class()
245                setattr(wrapper, "__instance__", self.__instance__)
246                return wrapper
247
248            return property(global_getter)
249
250        properties_and_callbacks[global_name] = mk_global(global_class)
251
252    return type("SlintClassWrapper", (Component,), properties_and_callbacks)
253
254
255def _build_struct(name: str, struct_prototype: native.PyStruct) -> type:
256    def new_struct(cls: Any, *args: Any, **kwargs: Any) -> native.PyStruct:
257        inst = copy.copy(struct_prototype)
258
259        for prop, val in kwargs.items():
260            setattr(inst, prop, val)
261
262        return inst
263
264    type_dict = {
265        "__new__": new_struct,
266    }
267
268    return type(name, (), type_dict)
269
270
271def load_file(
272    path: str | os.PathLike[Any] | pathlib.Path,
273    quiet: bool = False,
274    style: typing.Optional[str] = None,
275    include_paths: typing.Optional[typing.List[os.PathLike[Any] | pathlib.Path]] = None,
276    library_paths: typing.Optional[
277        typing.Dict[str, os.PathLike[Any] | pathlib.Path]
278    ] = None,
279    translation_domain: typing.Optional[str] = None,
280) -> types.SimpleNamespace:
281    """This function is the low-level entry point into Slint for instantiating components. It loads the `.slint` file at
282    the specified `path` and returns a namespace with all exported components as Python classes, as well as enums, and structs.
283
284    * `quiet`: Set to true to prevent any warnings during compilation from being printed to stderr.
285    * `style`: Specify a widget style.
286    * `include_paths`: Additional include paths used to look up `.slint` files imported from other `.slint` files.
287    * `library_paths`: A dictionary that maps library names to their location in the file system. This is then used to look up
288       library imports, such as `import { MyButton } from "@mylibrary";`.
289    * `translation_domain`: The domain to use for looking up the catalogue run-time translations. This must match the
290       translation domain used when extracting translations with `slint-tr-extractor`.
291
292    """
293
294    compiler = native.Compiler()
295
296    if style is not None:
297        compiler.style = style
298    if include_paths is not None:
299        compiler.include_paths = include_paths
300    if library_paths is not None:
301        compiler.library_paths = library_paths
302    if translation_domain is not None:
303        compiler.translation_domain = translation_domain
304
305    result = compiler.build_from_path(Path(path))
306
307    diagnostics = result.diagnostics
308    if diagnostics:
309        if not quiet:
310            for diag in diagnostics:
311                if diag.level == native.DiagnosticLevel.Warning:
312                    logging.warning(diag)
313
314        errors = [
315            diag for diag in diagnostics if diag.level == native.DiagnosticLevel.Error
316        ]
317        if errors:
318            raise CompileError(f"Could not compile {path}", diagnostics)
319
320    module = types.SimpleNamespace()
321    for comp_name in result.component_names:
322        wrapper_class = _build_class(result.component(comp_name))
323
324        setattr(module, comp_name, wrapper_class)
325
326    structs, enums = result.structs_and_enums
327
328    for name, struct_prototype in structs.items():
329        name = _normalize_prop(name)
330        struct_wrapper = _build_struct(name, struct_prototype)
331        setattr(module, name, struct_wrapper)
332
333    for name, enum_class in enums.items():
334        name = _normalize_prop(name)
335        setattr(module, name, enum_class)
336
337    for orig_name, new_name in result.named_exports:
338        orig_name = _normalize_prop(orig_name)
339        new_name = _normalize_prop(new_name)
340        setattr(module, new_name, getattr(module, orig_name))
341
342    return module
343
344
345class SlintAutoLoader:
346    def __init__(self, base_dir: Path | None = None):
347        self.local_dirs: typing.List[Path] | None = None
348        if base_dir:
349            self.local_dirs = [base_dir]
350
351    def __getattr__(self, name: str) -> Any:
352        for path in self.local_dirs or sys.path:
353            dir_candidate = Path(path) / name
354            if os.path.isdir(dir_candidate):
355                loader = SlintAutoLoader(dir_candidate)
356                setattr(self, name, loader)
357                return loader
358
359            file_candidate = dir_candidate.with_suffix(".slint")
360            if os.path.isfile(file_candidate):
361                type_namespace = load_file(file_candidate)
362                setattr(self, name, type_namespace)
363                return type_namespace
364
365            dir_candidate = Path(path) / name.replace("_", "-")
366            file_candidate = dir_candidate.with_suffix(".slint")
367            if os.path.isfile(file_candidate):
368                type_namespace = load_file(file_candidate)
369                setattr(self, name, type_namespace)
370                return type_namespace
371
372        return None
373
374
375loader = SlintAutoLoader()
376"""Use the global `loader` object to load Slint files from the file system. It exposes two stages of attributes:
3771. Any lookup of an attribute in the loader tries to match a file in `sys.path` with the `.slint` extension. For example
378   `loader.my_component` looks for a file `my_component.slint` in the directories in `sys.path`.
3792. Any lookup in the object returned by the first stage tries to match an exported component in the loaded file, or a
380   struct, or enum. For example `loader.my_component.MyComponent` looks for an *exported* component named `MyComponent`
381   in the file `my_component.slint`.
382
383**Note:** The first entry in the module search path `sys.path` is the directory that contains the input script.
384
385Example:
386```python
387import slint
388# Look for a file `main.slint` in the current directory,
389# #load & compile it, and instantiate the exported `MainWindow` component
390main_window = slint.loader.main_window.MainWindow()
391main_window.show()
392...
393```
394"""
395
396
397def _callback_decorator(
398    callable: typing.Callable[..., Any], info: typing.Dict[str, Any]
399) -> typing.Callable[..., Any]:
400    if "name" not in info:
401        info["name"] = callable.__name__
402    setattr(callable, "slint.callback", info)
403
404    try:
405        import inspect
406
407        if inspect.iscoroutinefunction(callable):
408
409            def run_as_task(*args, **kwargs) -> None:  # type: ignore
410                loop = asyncio.get_event_loop()
411                loop.create_task(callable(*args, **kwargs))
412
413            setattr(run_as_task, "slint.callback", info)
414            setattr(run_as_task, "slint.async", True)
415            return run_as_task
416    except ImportError:
417        pass
418
419    return callable
420
421
422def callback(
423    global_name: str | None = None, name: str | None = None
424) -> typing.Callable[..., Any]:
425    """Use the callback decorator to mark a method as a callback that can be invoked from the Slint component.
426
427    For the decorator to work, the method must be a member of a class that is Slint component.
428
429    Example:
430    ```python
431    import slint
432
433    class AppMainWindow(slint.loader.main_window.MainWindow):
434
435        # Automatically connected to a callback button_clicked()
436        # in main_window.slint's MainWindow.
437        @slint.callback()
438        def button_clicked(self):
439            print("Button clicked")
440
441    ...
442    ```
443
444    If your Python method has a different name from the Slint component's callback, use the `name` parameter to specify
445    the correct name. Similarly, use the `global_name` parameter to specify the name of the correct global singleton in
446    the Slint component.
447
448    **Note:** The callback decorator can also be used with async functions. They will be run as task in the asyncio event loop.
449    This is only supported for callbacks that don't return any value, and requires Python >= 3.13.
450    """
451
452    if callable(global_name):
453        callback = global_name
454        return _callback_decorator(callback, {})
455    else:
456        info = {}
457        if name:
458            info["name"] = name
459        if global_name:
460            info["global_name"] = global_name
461        return lambda callback: _callback_decorator(callback, info)
462
463
464def set_xdg_app_id(app_id: str) -> None:
465    """Sets the application id for use on Wayland or X11 with [xdg](https://specifications.freedesktop.org/desktop-entry-spec/latest/)
466    compliant window managers. This id must be set before the window is shown; it only applies to Wayland or X11."""
467
468    native.set_xdg_app_id(app_id)
469
470
471quit_event = asyncio.Event()
472
473
474def run_event_loop(
475    main_coro: typing.Optional[Coroutine[None, None, None]] = None,
476) -> None:
477    """Runs the main Slint event loop. If specified, the coroutine `main_coro` is run in parallel. The event loop doesn't
478    terminate when the coroutine finishes, it terminates when calling `quit_event_loop()`.
479
480    Example:
481    ```python
482    import slint
483
484    ...
485    image_model: slint.ListModel[slint.Image] = slint.ListModel()
486    ...
487
488    async def main_receiver(image_model: slint.ListModel) -> None:
489        async with aiohttp.ClientSession() as session:
490            async with session.get("http://some.server/svg-image") as response:
491                svg = await response.read()
492                image = slint.Image.from_svg_data(svg)
493                image_model.append(image)
494
495    ...
496    slint.run_event_loop(main_receiver(image_model))
497    ```
498
499    """
500
501    async def run_inner() -> None:
502        global quit_event
503        loop = typing.cast(SlintEventLoop, asyncio.get_event_loop())
504
505        quit_task = asyncio.ensure_future(quit_event.wait(), loop=loop)
506
507        tasks: typing.List[asyncio.Task[typing.Any]] = [quit_task]
508
509        main_task = None
510        if main_coro:
511            main_task = loop.create_task(main_coro)
512            tasks.append(main_task)
513
514        done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
515
516        if main_task is not None and main_task in done:
517            main_task.result()  # propagate exception if thrown
518            if quit_task in pending:
519                await quit_event.wait()
520
521    global quit_event
522    quit_event = asyncio.Event()
523    asyncio.run(run_inner(), debug=False, loop_factory=SlintEventLoop)
524
525
526def quit_event_loop() -> None:
527    """Quits the running event loop in the next event processing cycle. This will make an earlier call to `run_event_loop()`
528    return."""
529    global quit_event
530    quit_event.set()
531
532
533def init_translations(translations: typing.Optional[gettext.GNUTranslations]) -> None:
534    """Installs the specified translations object to handle translations originating from the Slint code.
535
536    Example:
537    ```python
538    import gettext
539    import slint
540
541    translations_dir = os.path.join(os.path.dirname(__file__), "lang")
542    try:
543        translations = gettext.translation("my_app", translations_dir, ["de"])
544        slint.install_translations(translations)
545    except OSError:
546        pass
547    ```
548    """
549    native.init_translations(translations)
550
551
552__all__ = [
553    "CompileError",
554    "Component",
555    "load_file",
556    "loader",
557    "Image",
558    "Color",
559    "Brush",
560    "Model",
561    "ListModel",
562    "Timer",
563    "TimerMode",
564    "set_xdg_app_id",
565    "callback",
566    "run_event_loop",
567    "quit_event_loop",
568    "init_translations",
569]
class CompileError(builtins.Exception):
29class CompileError(Exception):
30    message: str
31    """The error message that produced this compile error."""
32
33    diagnostics: list[native.PyDiagnostic]
34    """A list of detailed diagnostics that were produced as part of the compilation."""
35
36    def __init__(self, message: str, diagnostics: list[native.PyDiagnostic]):
37        """@private"""
38        super().__init__(message)
39        self.message = message
40        self.diagnostics = diagnostics
41        for diag in self.diagnostics:
42            self.add_note(str(diag))

Common base class for all non-exit exceptions.

message: str

The error message that produced this compile error.

diagnostics: list[PyDiagnostic]

A list of detailed diagnostics that were produced as part of the compilation.

class Component:
45class Component:
46    """Component is the base class for all instances of Slint components. Use the member functions to show or hide the
47    window, or spin the event loop."""
48
49    __instance__: native.ComponentInstance
50
51    def show(self) -> None:
52        """Shows the window on the screen."""
53
54        self.__instance__.show()
55
56    def hide(self) -> None:
57        """Hides the window from the screen."""
58
59        self.__instance__.hide()
60
61    def run(self) -> None:
62        """Shows the window, runs the event loop, hides it when the loop is quit, and returns."""
63        self.show()
64        run_event_loop()
65        self.hide()

Component is the base class for all instances of Slint components. Use the member functions to show or hide the window, or spin the event loop.

def show(self) -> None:
51    def show(self) -> None:
52        """Shows the window on the screen."""
53
54        self.__instance__.show()

Shows the window on the screen.

def hide(self) -> None:
56    def hide(self) -> None:
57        """Hides the window from the screen."""
58
59        self.__instance__.hide()

Hides the window from the screen.

def run(self) -> None:
61    def run(self) -> None:
62        """Shows the window, runs the event loop, hides it when the loop is quit, and returns."""
63        self.show()
64        run_event_loop()
65        self.hide()

Shows the window, runs the event loop, hides it when the loop is quit, and returns.

def load_file( path: str | os.PathLike[typing.Any] | pathlib.Path, quiet: bool = False, style: Optional[str] = None, include_paths: Optional[List[os.PathLike[Any] | pathlib.Path]] = None, library_paths: Optional[Dict[str, os.PathLike[Any] | pathlib.Path]] = None, translation_domain: Optional[str] = None) -> types.SimpleNamespace:
272def load_file(
273    path: str | os.PathLike[Any] | pathlib.Path,
274    quiet: bool = False,
275    style: typing.Optional[str] = None,
276    include_paths: typing.Optional[typing.List[os.PathLike[Any] | pathlib.Path]] = None,
277    library_paths: typing.Optional[
278        typing.Dict[str, os.PathLike[Any] | pathlib.Path]
279    ] = None,
280    translation_domain: typing.Optional[str] = None,
281) -> types.SimpleNamespace:
282    """This function is the low-level entry point into Slint for instantiating components. It loads the `.slint` file at
283    the specified `path` and returns a namespace with all exported components as Python classes, as well as enums, and structs.
284
285    * `quiet`: Set to true to prevent any warnings during compilation from being printed to stderr.
286    * `style`: Specify a widget style.
287    * `include_paths`: Additional include paths used to look up `.slint` files imported from other `.slint` files.
288    * `library_paths`: A dictionary that maps library names to their location in the file system. This is then used to look up
289       library imports, such as `import { MyButton } from "@mylibrary";`.
290    * `translation_domain`: The domain to use for looking up the catalogue run-time translations. This must match the
291       translation domain used when extracting translations with `slint-tr-extractor`.
292
293    """
294
295    compiler = native.Compiler()
296
297    if style is not None:
298        compiler.style = style
299    if include_paths is not None:
300        compiler.include_paths = include_paths
301    if library_paths is not None:
302        compiler.library_paths = library_paths
303    if translation_domain is not None:
304        compiler.translation_domain = translation_domain
305
306    result = compiler.build_from_path(Path(path))
307
308    diagnostics = result.diagnostics
309    if diagnostics:
310        if not quiet:
311            for diag in diagnostics:
312                if diag.level == native.DiagnosticLevel.Warning:
313                    logging.warning(diag)
314
315        errors = [
316            diag for diag in diagnostics if diag.level == native.DiagnosticLevel.Error
317        ]
318        if errors:
319            raise CompileError(f"Could not compile {path}", diagnostics)
320
321    module = types.SimpleNamespace()
322    for comp_name in result.component_names:
323        wrapper_class = _build_class(result.component(comp_name))
324
325        setattr(module, comp_name, wrapper_class)
326
327    structs, enums = result.structs_and_enums
328
329    for name, struct_prototype in structs.items():
330        name = _normalize_prop(name)
331        struct_wrapper = _build_struct(name, struct_prototype)
332        setattr(module, name, struct_wrapper)
333
334    for name, enum_class in enums.items():
335        name = _normalize_prop(name)
336        setattr(module, name, enum_class)
337
338    for orig_name, new_name in result.named_exports:
339        orig_name = _normalize_prop(orig_name)
340        new_name = _normalize_prop(new_name)
341        setattr(module, new_name, getattr(module, orig_name))
342
343    return module

This function is the low-level entry point into Slint for instantiating components. It loads the .slint file at the specified path and returns a namespace with all exported components as Python classes, as well as enums, and structs.

  • quiet: Set to true to prevent any warnings during compilation from being printed to stderr.
  • style: Specify a widget style.
  • include_paths: Additional include paths used to look up .slint files imported from other .slint files.
  • library_paths: A dictionary that maps library names to their location in the file system. This is then used to look up library imports, such as import { MyButton } from "@mylibrary";.
  • translation_domain: The domain to use for looking up the catalogue run-time translations. This must match the translation domain used when extracting translations with slint-tr-extractor.
loader = <slint.SlintAutoLoader object>

Use the global loader object to load Slint files from the file system. It exposes two stages of attributes:

  1. Any lookup of an attribute in the loader tries to match a file in sys.path with the .slint extension. For example loader.my_component looks for a file my_component.slint in the directories in sys.path.
  2. Any lookup in the object returned by the first stage tries to match an exported component in the loaded file, or a struct, or enum. For example loader.my_component.MyComponent looks for an exported component named MyComponent in the file my_component.slint.

Note: The first entry in the module search path sys.path is the directory that contains the input script.

Example:

import slint
# Look for a file `main.slint` in the current directory,
# #load & compile it, and instantiate the exported `MainWindow` component
main_window = slint.loader.main_window.MainWindow()
main_window.show()
...
class Image:

Image objects can be set on Slint Image elements for display. Use Image.load_from_path to construct Image objects from a path to an image file on disk.

def load_from_path(path):

Loads the image from the specified path. Returns None if the image can't be loaded.

def load_from_svg_data(data):

Creates a new image from a string that describes the image in SVG format.

def load_from_array(array):

Creates a new image from an array-like object that implements the Buffer Protocol. Use this function to import images created by third-party modules such as matplotlib or Pillow.

The array must satisfy certain contraints to represent an image:

  • The buffer's format needs to be B (unsigned char)
  • The shape must be a tuple of (height, width, bytes-per-pixel)
  • If a stride is defined, the row stride must be equal to width * bytes-per-pixel, and the column stride must equal the bytes-per-pixel.
  • A value of 3 for bytes-per-pixel is interpreted as RGB image, a value of 4 means RGBA.

The image is created by performing a deep copy of the array's data. Subsequent changes to the buffer are not automatically reflected in a previously created Image.

Example of importing a matplot figure into an image:

import slint
import matplotlib

from matplotlib.backends.backend_agg import FigureCanvasAgg
from matplotlib.figure import Figure

fig = Figure(figsize=(5, 4), dpi=100)
canvas = FigureCanvasAgg(fig)
ax = fig.add_subplot()
ax.plot([1, 2, 3])
canvas.draw()

buffer = canvas.buffer_rgba()
img = slint.Image.load_from_array(buffer)

Example of loading an image with Pillow:

import slint
from PIL import Image
import numpy as np

pil_img = Image.open("hello.jpeg")
array = np.array(pil_img)
img = slint.Image.load_from_array(array)
size

The size of the image as tuple of width and height.

width

The width of the image in pixels.

height

The height of the image in pixels.

path

The path of the image if it was loaded from disk, or None.

class Color:

A Color object represents a color in the RGB color space with an alpha. Each color channel and the alpha is represented as an 8-bit integer. The alpha channel is 0 for fully transparent and 255 for fully opaque.

Construct colors from a CSS color string, or by specifying the red, green, blue, and (optional) alpha channels in a dict.

def brighter(self, /, factor):

Returns a new color that is brighter than this color by the given factor.

def darker(self, /, factor):

Returns a new color that is darker than this color by the given factor.

def transparentize(self, /, factor):

Returns a new version of this color with the opacity decreased by factor.

The transparency is obtained by multiplying the alpha channel by (1 - factor).

def mix(self, /, other, factor):

Returns a new color that is a mix of this color and other. The specified factor is clamped to be between 0.0 and 1.0 and then applied to this color, while 1.0 - factor is applied to other.

def with_alpha(self, /, alpha):

Returns a new version of this color with the opacity set to alpha.

blue

The blue channel.

red

The red channel.

alpha

The alpha channel.

green

The green channel.

class Brush:

A brush is a data structure that is used to describe how a shape, such as a rectangle, path or even text, shall be filled. A brush can also be applied to the outline of a shape, that means the fill of the outline itself.

Brushes can only be constructed from solid colors.

Note: In future, we plan to reduce this constraint and allow for declaring graidient brushes programmatically.

def is_transparent(self, /):

Returns true if this brush contains a fully transparent color (alpha value is zero).

def is_opaque(self, /):

Returns true if this brush is fully opaque.

def brighter(self, /, factor):

Returns a new version of this brush that has the brightness increased by the specified factor. This is done by calling Color.brighter on all the colors of this brush.

def darker(self, /, factor):

Returns a new version of this brush that has the brightness decreased by the specified factor. This is done by calling Color.darker on all the color of this brush.

def transparentize(self, /, amount):

Returns a new version of this brush with the opacity decreased by factor.

The transparency is obtained by multiplying the alpha channel by (1 - factor).

See also Color.transparentize.

def with_alpha(self, /, alpha):

Returns a new version of this brush with the related color's opacities set to alpha.

color

The brush's color.

class Model(builtins.PyModelBase, collections.abc.Iterable[T], typing.Generic[T]):
12class Model[T](native.PyModelBase, Iterable[T]):
13    """Model is the base class for feeding dynamic data into Slint views.
14
15    Subclass Model to implement your own models, or use `ListModel` to wrap a list.
16
17    Models are iterable and can be used in for loops."""
18
19    def __new__(cls, *args: Any) -> "Model[T]":
20        return super().__new__(cls)
21
22    def __init__(self) -> None:
23        self.init_self(self)
24
25    def __len__(self) -> int:
26        return self.row_count()
27
28    def __getitem__(self, index: int) -> typing.Optional[T]:
29        return self.row_data(index)
30
31    def __setitem__(self, index: int, value: T) -> None:
32        self.set_row_data(index, value)
33
34    def __iter__(self) -> Iterator[T]:
35        return ModelIterator(self)
36
37    def set_row_data(self, row: int, value: T) -> None:
38        """Call this method on mutable models to change the data for the given row.
39        The UI will also call this method when modifying a model's data.
40        Re-implement this method in a sub-class to handle the change."""
41        super().set_row_data(row, value)
42
43    @abstractmethod
44    def row_data(self, row: int) -> typing.Optional[T]:
45        """Returns the data for the given row.
46        Re-implement this method in a sub-class to provide the data."""
47        return cast(T, super().row_data(row))
48
49    def notify_row_changed(self, row: int) -> None:
50        """Call this method from a sub-class to notify the views that a row has changed."""
51        super().notify_row_changed(row)
52
53    def notify_row_removed(self, row: int, count: int) -> None:
54        """Call this method from a sub-class to notify the views that
55        `count` rows have been removed starting at `row`."""
56        super().notify_row_removed(row, count)
57
58    def notify_row_added(self, row: int, count: int) -> None:
59        """Call this method from a sub-class to notify the views that
60        `count` rows have been added starting at `row`."""
61        super().notify_row_added(row, count)

Model is the base class for feeding dynamic data into Slint views.

Subclass Model to implement your own models, or use ListModel to wrap a list.

Models are iterable and can be used in for loops.

def set_row_data(self, row: int, value: T) -> None:
37    def set_row_data(self, row: int, value: T) -> None:
38        """Call this method on mutable models to change the data for the given row.
39        The UI will also call this method when modifying a model's data.
40        Re-implement this method in a sub-class to handle the change."""
41        super().set_row_data(row, value)

Call this method on mutable models to change the data for the given row. The UI will also call this method when modifying a model's data. Re-implement this method in a sub-class to handle the change.

@abstractmethod
def row_data(self, row: int) -> Optional[T]:
43    @abstractmethod
44    def row_data(self, row: int) -> typing.Optional[T]:
45        """Returns the data for the given row.
46        Re-implement this method in a sub-class to provide the data."""
47        return cast(T, super().row_data(row))

Returns the data for the given row. Re-implement this method in a sub-class to provide the data.

def notify_row_changed(self, /, index):

Call this method from a sub-class to notify the views that a row has changed.

def notify_row_removed(self, /, index, count):

Call this method from a sub-class to notify the views that count rows have been removed starting at row.

def notify_row_added(self, /, index, count):

Call this method from a sub-class to notify the views that count rows have been added starting at row.

class ListModel(slint.Model[T], typing.Generic[T]):
 64class ListModel[T](Model[T]):
 65    """ListModel is a `Model` that stores its data in a Python list.
 66
 67    Construct a ListMode from an iterable (such as a list itself).
 68    Use `ListModel.append()` to add items to the model, and use the
 69    `del` statement to remove items.
 70
 71    Any changes to the model are automatically reflected in the views
 72    in UI they're used with.
 73    """
 74
 75    def __init__(self, iterable: typing.Optional[Iterable[T]] = None):
 76        """Constructs a new ListModel from the give iterable. All the values
 77        the iterable produces are stored in a list."""
 78
 79        super().__init__()
 80        if iterable is not None:
 81            self.list = list(iterable)
 82        else:
 83            self.list = []
 84
 85    def row_count(self) -> int:
 86        return len(self.list)
 87
 88    def row_data(self, row: int) -> typing.Optional[T]:
 89        return self.list[row]
 90
 91    def set_row_data(self, row: int, data: T) -> None:
 92        self.list[row] = data
 93        super().notify_row_changed(row)
 94
 95    def __delitem__(self, key: int | slice) -> None:
 96        if isinstance(key, slice):
 97            start, stop, step = key.indices(len(self.list))
 98            del self.list[key]
 99            count = len(range(start, stop, step))
100            super().notify_row_removed(start, count)
101        else:
102            del self.list[key]
103            super().notify_row_removed(key, 1)
104
105    def append(self, value: T) -> None:
106        """Appends the value to the end of the list."""
107        index = len(self.list)
108        self.list.append(value)
109        super().notify_row_added(index, 1)

ListModel is a Model that stores its data in a Python list.

Construct a ListMode from an iterable (such as a list itself). Use ListModel.append() to add items to the model, and use the del statement to remove items.

Any changes to the model are automatically reflected in the views in UI they're used with.

ListModel(iterable: Optional[Iterable[T]] = None)
75    def __init__(self, iterable: typing.Optional[Iterable[T]] = None):
76        """Constructs a new ListModel from the give iterable. All the values
77        the iterable produces are stored in a list."""
78
79        super().__init__()
80        if iterable is not None:
81            self.list = list(iterable)
82        else:
83            self.list = []

Constructs a new ListModel from the give iterable. All the values the iterable produces are stored in a list.

def row_count(self) -> int:
85    def row_count(self) -> int:
86        return len(self.list)
def row_data(self, row: int) -> Optional[T]:
88    def row_data(self, row: int) -> typing.Optional[T]:
89        return self.list[row]

Returns the data for the given row. Re-implement this method in a sub-class to provide the data.

def set_row_data(self, row: int, data: T) -> None:
91    def set_row_data(self, row: int, data: T) -> None:
92        self.list[row] = data
93        super().notify_row_changed(row)

Call this method on mutable models to change the data for the given row. The UI will also call this method when modifying a model's data. Re-implement this method in a sub-class to handle the change.

def append(self, value: T) -> None:
105    def append(self, value: T) -> None:
106        """Appends the value to the end of the list."""
107        index = len(self.list)
108        self.list.append(value)
109        super().notify_row_added(index, 1)

Appends the value to the end of the list.

class Timer:

Timer is a handle to the timer system that triggers a callback after a specified period of time.

Use Timer.start() to create a timer that that repeatedly triggers a callback, or Timer.single_shot() to trigger a callback only once.

The timer will automatically stop when garbage collected. You must keep the Timer object around for as long as you want the timer to keep firing.

class AppWindow(...)
    def __init__(self):
        super().__init__()
        self.my_timer = None

    @slint.callback
    def button_clicked(self):
        self.my_timer = slint.Timer()
        self.my_timer.start(timedelta(seconds=1), self.do_something)

    def do_something(self):
        pass

Timers can only be used in the thread that runs the Slint event loop. They don't fire if used in another thread.

def start(self, /, mode, interval, callback):

Starts the timer with the given mode and interval, in order for the callback to called when the timer fires. If the timer has been started previously and not fired yet, then it will be restarted.

Arguments:

  • mode: The timer mode to apply, i.e. whether to repeatedly fire the timer or just once.
  • interval: The duration from now until when the timer should firethe first time, and subsequently for TimerMode.Repeated timers.
  • callback: The function to call when the time has been reached or exceeded.
def single_shot(duration, callback):

Starts the timer with the duration and the callback to called when the timer fires. It is fired only once and then deleted.

Arguments:

  • duration: The duration from now until when the timer should fire.
  • callback: The function to call when the time has been reached or exceeded.
def stop(self, /):

Stops the previously started timer. Does nothing if the timer has never been started.

def restart(self, /):

Restarts the timer. If the timer was previously started by calling Timer.start() with a duration and callback, then the time when the callback will be next invoked is re-calculated to be in the specified duration relative to when this function is called.

Does nothing if the timer was never started.

interval

The duration of timer.

When setting this property and the timer is running (see Timer.running), then the time when the callback will be next invoked is re-calculated to be in the specified duration relative to when this property is set.

running

Set to true if the timer is running; false otherwise.

class TimerMode:

The TimerMode specifies what should happen after the timer fired.

Used by the Timer.start() function.

SingleShot = TimerMode.SingleShot
Repeated = TimerMode.Repeated
def set_xdg_app_id(app_id: str) -> None:
465def set_xdg_app_id(app_id: str) -> None:
466    """Sets the application id for use on Wayland or X11 with [xdg](https://specifications.freedesktop.org/desktop-entry-spec/latest/)
467    compliant window managers. This id must be set before the window is shown; it only applies to Wayland or X11."""
468
469    native.set_xdg_app_id(app_id)

Sets the application id for use on Wayland or X11 with xdg compliant window managers. This id must be set before the window is shown; it only applies to Wayland or X11.

def callback( global_name: str | None = None, name: str | None = None) -> Callable[..., Any]:
423def callback(
424    global_name: str | None = None, name: str | None = None
425) -> typing.Callable[..., Any]:
426    """Use the callback decorator to mark a method as a callback that can be invoked from the Slint component.
427
428    For the decorator to work, the method must be a member of a class that is Slint component.
429
430    Example:
431    ```python
432    import slint
433
434    class AppMainWindow(slint.loader.main_window.MainWindow):
435
436        # Automatically connected to a callback button_clicked()
437        # in main_window.slint's MainWindow.
438        @slint.callback()
439        def button_clicked(self):
440            print("Button clicked")
441
442    ...
443    ```
444
445    If your Python method has a different name from the Slint component's callback, use the `name` parameter to specify
446    the correct name. Similarly, use the `global_name` parameter to specify the name of the correct global singleton in
447    the Slint component.
448
449    **Note:** The callback decorator can also be used with async functions. They will be run as task in the asyncio event loop.
450    This is only supported for callbacks that don't return any value, and requires Python >= 3.13.
451    """
452
453    if callable(global_name):
454        callback = global_name
455        return _callback_decorator(callback, {})
456    else:
457        info = {}
458        if name:
459            info["name"] = name
460        if global_name:
461            info["global_name"] = global_name
462        return lambda callback: _callback_decorator(callback, info)

Use the callback decorator to mark a method as a callback that can be invoked from the Slint component.

For the decorator to work, the method must be a member of a class that is Slint component.

Example:

import slint

class AppMainWindow(slint.loader.main_window.MainWindow):

    # Automatically connected to a callback button_clicked()
    # in main_window.slint's MainWindow.
    @slint.callback()
    def button_clicked(self):
        print("Button clicked")

...

If your Python method has a different name from the Slint component's callback, use the name parameter to specify the correct name. Similarly, use the global_name parameter to specify the name of the correct global singleton in the Slint component.

Note: The callback decorator can also be used with async functions. They will be run as task in the asyncio event loop. This is only supported for callbacks that don't return any value, and requires Python >= 3.13.

def run_event_loop(main_coro: Optional[Coroutine[None, None, None]] = None) -> None:
475def run_event_loop(
476    main_coro: typing.Optional[Coroutine[None, None, None]] = None,
477) -> None:
478    """Runs the main Slint event loop. If specified, the coroutine `main_coro` is run in parallel. The event loop doesn't
479    terminate when the coroutine finishes, it terminates when calling `quit_event_loop()`.
480
481    Example:
482    ```python
483    import slint
484
485    ...
486    image_model: slint.ListModel[slint.Image] = slint.ListModel()
487    ...
488
489    async def main_receiver(image_model: slint.ListModel) -> None:
490        async with aiohttp.ClientSession() as session:
491            async with session.get("http://some.server/svg-image") as response:
492                svg = await response.read()
493                image = slint.Image.from_svg_data(svg)
494                image_model.append(image)
495
496    ...
497    slint.run_event_loop(main_receiver(image_model))
498    ```
499
500    """
501
502    async def run_inner() -> None:
503        global quit_event
504        loop = typing.cast(SlintEventLoop, asyncio.get_event_loop())
505
506        quit_task = asyncio.ensure_future(quit_event.wait(), loop=loop)
507
508        tasks: typing.List[asyncio.Task[typing.Any]] = [quit_task]
509
510        main_task = None
511        if main_coro:
512            main_task = loop.create_task(main_coro)
513            tasks.append(main_task)
514
515        done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
516
517        if main_task is not None and main_task in done:
518            main_task.result()  # propagate exception if thrown
519            if quit_task in pending:
520                await quit_event.wait()
521
522    global quit_event
523    quit_event = asyncio.Event()
524    asyncio.run(run_inner(), debug=False, loop_factory=SlintEventLoop)

Runs the main Slint event loop. If specified, the coroutine main_coro is run in parallel. The event loop doesn't terminate when the coroutine finishes, it terminates when calling quit_event_loop().

Example:

import slint

...
image_model: slint.ListModel[slint.Image] = slint.ListModel()
...

async def main_receiver(image_model: slint.ListModel) -> None:
    async with aiohttp.ClientSession() as session:
        async with session.get("http://some.server/svg-image") as response:
            svg = await response.read()
            image = slint.Image.from_svg_data(svg)
            image_model.append(image)

...
slint.run_event_loop(main_receiver(image_model))
def quit_event_loop() -> None:
527def quit_event_loop() -> None:
528    """Quits the running event loop in the next event processing cycle. This will make an earlier call to `run_event_loop()`
529    return."""
530    global quit_event
531    quit_event.set()

Quits the running event loop in the next event processing cycle. This will make an earlier call to run_event_loop() return.

def init_translations(translations: Optional[gettext.GNUTranslations]) -> None:
534def init_translations(translations: typing.Optional[gettext.GNUTranslations]) -> None:
535    """Installs the specified translations object to handle translations originating from the Slint code.
536
537    Example:
538    ```python
539    import gettext
540    import slint
541
542    translations_dir = os.path.join(os.path.dirname(__file__), "lang")
543    try:
544        translations = gettext.translation("my_app", translations_dir, ["de"])
545        slint.install_translations(translations)
546    except OSError:
547        pass
548    ```
549    """
550    native.init_translations(translations)

Installs the specified translations object to handle translations originating from the Slint code.

Example:

import gettext
import slint

translations_dir = os.path.join(os.path.dirname(__file__), "lang")
try:
    translations = gettext.translation("my_app", translations_dir, ["de"])
    slint.install_translations(translations)
except OSError:
    pass