pyegui
pyegui is a native extenstion for Python that provides bindings for Rust immediate mode GUI library egui.
Example
from pyegui import *
name = Str("Van")
age = Int(24)
def update_func(ctx):
heading("My egui Application")
text_edit_singleline(name, hint_text="Your name")
slider_int(age, 0, 150, "age")
if button_clicked("Increment"):
age.value += 1
heading(f"Hello '{name.value}', age {age.value}")
image("file://image.png", max_width=350, max_height=250)
run_native("My pyegui Application", update_func)

Features
pyegui tries to be as close as possible to the original egui API, but with the focus on simplicity and usability. Callbacks were removed where possible to accomplish more smooth expirience in Python.
Light and Dark themes(defaults to the system’s)
Built-in latin and cyrillic alphabets. You can load any font you want with
ctx.set_fontfunctionImages(png and jpeg)
Date picker
RBG color picker
Text fields, radio buttons, buttons, code, progress bar etc.
No dependencies which destroy you project when you distribute it. Just pure giant Rust binary
Full list of implemented features is available here
Install
Prebuilt binaries are provided for Linux, Windows and macOS. On other platforms pip will build wheel for your OS. In this case you’ll need Rust compiler and maturin
Install from pypi:
pip install pyegui
Install from source:
git clone https://github.com/gachilord/pyegui
pip install <path to pyegui>
Usage
This is how you write a “hello world” app.
from pyegui import *
def update_func(ctx):
# draw UI here
heading("Hello, World!")
if __name__ == "__main__":
run_native("Example app", update_func)
You can find more examples in the documentation.
Update functions
pyegui has a notion of update functions which the library calls to draw your UI.
def update_func():
# you can place here any widget
heading("I'm a heading")
# some widgets are interactive
if button_clicked("I'm a clickable button"):
# you can update state from here or show another widget
print("Clicked")
The top level update function has the Context object that controls global aspects of your app(e.g fonts and theme).
def update_func(ctx):
ctx.set_light_theme()
heading("Using light theme even if system's is dark")
Update functions may be nested. Such functions create a new UI scope that can have different styles and behaviour.
def update_func(ctx):
# define update_func
def nested():
label("I'm a label inside nested update function")
label("New label")
disable() # this function will disable all further widgets in the scope
if button_clicked("You can't click me"):
print("Unreachable")
# all the widgets inside 'nested' will be centered vertically
horizontal_centered(nested)
# this widget won't be disabled though it goes after 'disable()'
if button_clicked("You can click me"):
print("Clicked")
Containers
Containers is a syntactic sugar for code that needs update functions.
Function calls are replaced by Python’s with statement.
The code that centers widgets vertically:
def update_func(ctx):
def nested():
label("I'm a label inside nested update function")
label("New label")
horizontal_centered(nested)
Can be written without callbacks:
def update_func(ctx):
with Layout(LayoutType.HorizontalCentered):
label("I'm a label inside nested update function")
label("New label")
Variables
Many widgets require access to a state via a reference, which can’t be done for integers, floats and strings in Python. That’s why such helper classes as Str, Bool, Int and Float exist.
They are essentially the following:
# Example for bool type
class Bool:
value = False
These classes can be used to draw UI or to store user input. You have to create them outside of update functions.
data = Bool(False)
def update_func():
heading(f"Value of the data is {data.value}")
# button will be shown only if the checkbox is checked
if data.value and button_clicked("set to False"):
# hiding the button
data.value = False
checkbox(data, "Check me")