PyHMI
Open-source, royalty-free Python graphics library for building graphical user interfaces on embedded systems and desktop Linux.
One Library, Three Runtimes
PyHMI bridges the gap between minimal embedded GUIs and full-featured frameworks. The same UI description runs across all platforms:
Desktop Linux
Direct rendering to /dev/fb0 framebuffer. No X11 or Wayland dependency. Runs on Raspberry Pi, BeagleBone, and any Linux SBC.
- Native framebuffer via mmap
- RGB565, RGB565_SWAPPED, RGB888, BGR888, GRAY1/2/4/8, RGB332
- evdev touch input
- <5 MB RAM
Microcontrollers
Runs on RP2350 microcontrollers (Raspberry Pi Pico 2) with MicroPython, rendering to SPI LCD displays. Supports ST7735, ST7789, ILI9341, and HX8357 controllers.
- MicroPython with C accelerator module
- Partial updates for efficiency
- USB HID input via tinyusb
- <500 KB RAM
Emulation
Cross-platform SDL2 window for design and testing. Runs on macOS, Linux, and Windows — no embedded hardware required.
- SDL2 rendering backend
- Keyboard and mouse input
- Identical PyHML files
- 60 FPS target
Declarative UI with PyHML
PyHMI uses PyHML (PyHMI Markup Language) — a YAML-compatible, QML-inspired syntax for describing UIs declaratively:
Window:
width: 320
height: 240
title: "Dashboard"
layout: Column
children:
- Label:
text: "Temperature"
font_size: 16
- Slider:
id: tempSlider
min_value: 0
max_value: 100
value: 22
onValueChanged: print("Temp:", value)
- Label:
text: "{{ tempSlider.value }} C"
PyHML supports component hierarchy, property binding, signal handlers, data binding, and layout declarations. PyHMI also supports QML import for loading existing Qt QML designs.
Comprehensive Widget Catalog
PyHMI ships with 72 widgets, covering all elements from uGUI, LVGL, TouchGFX, emWin, and Qt/Quick, plus 180+ runnable examples (including PyHML-language scenes). Browse the interactive gallery:
Basic
Label, Button, CheckBox, RadioButton, Switch, Slider, ProgressBar, Dial, TextField, Image, LED, DropDown
Input
VirtualKeyboard, TextArea, ComboBox, Spinbox, ButtonMatrix, SearchField, Roller, Tumbler
Container
Container, Frame, GroupBox, ScrollView, Window, Page, SplitView, Drawer
Chart / Graph
LineChart, AreaChart, BarChart, Gauge, Arc, Meter, Scale, LED
Media
Canvas, Video, GIF, AnimationImage
Navigation
TabBar, TabView, Menu, MenuBar, StackView, SwipeView, TileView, PageIndicator
Key Features
Layout Engine
Flex (row/column) and Grid layouts with alignment, spacing, stretch, and span. Responsive across resolutions.
Data Binding
One-way and two-way binding between widget properties and data models. Observable properties with dependency tracking.
Animations
Property animations with easing curves, keyframes, and timeline support. Declarative in PyHML.
Style Templates
Reusable style definitions at widget, class, or theme level. Cascade properties for consistent theming.
Theme System
Declarative .pyhmt themes with semantic colors, fonts and radii. Load them by name or via the editor's open-file dialog, set the screen background color, and switch the whole look without touching the UI description.
UI Scene Editor
Cross-platform visual editor (SDL2): widget palette with screenshot faces, live canvas, property pane, undo/redo, scene tree, snapping, themes and a standalone emulated preview window.
Scene Management
Load, unload, and navigate between scenes. Dynamic loading from Python code. Data segue between scenes.
Custom Elements
Define custom widgets via class inheritance. Nestable in PyHML and other custom elements. Full Python control.
C Graphics Core
Portable C99 core (pyhmi_fb) for fast memory graphics: pixel, rect, line, circle, arc, glyph blit, image blit. All colour formats and rotations. Ships as a MicroPython C module and a CPython extension; the Python painter falls back pixel-identically.
C/C++ Runtime
A C++11 runtime variant (pyhmi_cpp) with the same widget set, layouts, scenes, and PyHML parsing — for C-only deployments. Same example portfolio, CMake build, Debian packages.
Market Position
PyHMI fills the gap between minimal embedded GUIs and full-featured desktop frameworks:
| Feature | uGUI | LVGL | TouchGFX | Qt/Quick | PyHMI |
|---|---|---|---|---|---|
| Language | C | C | C++ | C++ / QML | Python |
| Declarative UI | No | XML (Pro) | Designer | QML | PyHML + QML |
| Linux framebuffer | No | Yes | No | Yes | Yes |
| SPI LCD / MCU | No | Yes | No | No | Yes |
| Memory (desktop) | ~10 KB | ~32 KB | ~1-2 MB | ~100+ MB | ~2 MB |
| Widgets | 6 | 38+ | 24+ | 50+ | 70+ |
| License | MIT | MIT | Commercial | LGPL v3 | Apache 2.0 |
| Emulation | No | Simulator | Designer | Native | SDL2 |
Quick Start
1. Install
git clone https://github.com/schreinerman/pyhmi
cd pyhmi
bash install.sh
source .venv/bin/activate
2. Minimal Example
from pyhmi import (
Engine, Sdl2Display,
Label, Window, FlexLayout
)
display = Sdl2Display(
width=320, height=240,
title="Hello PyHMI"
)
engine = Engine(display)
window = Window()
window.width = 320
window.height = 240
window.background_color = (30, 30, 30, 255)
label = Label()
label.text = "Hello, PyHMI!"
label.font_size = 20
label.text_color = (255, 255, 255)
window.add_child(label)
engine.set_root(window)
engine.run()
3. PyHML File
from pyhmi import (
Engine, Sdl2Display,
PyHMLParser, FlexLayout
)
display = Sdl2Display(
width=320, height=240
)
engine = Engine(display)
parser = PyHMLParser(engine)
root = parser.parse_file(
"dashboard.pyhml"
)
engine.set_root(root)
engine.run()
4. Project Generator
# Quick start (2 questions)
python -m pyhmi.cli.generator \
--simple myproject
# Full wizard (8 questions)
python -m pyhmi.cli.generator \
--advanced myproject