pdwidgets
pdwidgets
pdwidgets
Provides a collection of widgets for creating graphical user interfaces on embedded systems. It includes base classes for widgets, as well as specific widgets such as buttons, labels, sliders, and more.
Core (always imported): Display, Screen, Task, Widget, themes, constants.
Widgets load lazily via __getattr__ so MCU images only pay for modules you
touch. Lean path::
from pdwidgets.widgets.button import Button
Convenience::
import pdwidgets as pd
pd.Button(...) # imports widgets.button on first access
See WIDGET_DEPS.md for the peer import graph.
Optional add-on dependency
Label (and widgets built on it) gains proportional-font rendering when a
font module is supplied. That path lazily imports add_ons/tft_write.
Timer architecture
pdwidgets owns no timer of its own. Each :class:Display wires itself
into the shared eventsys.Runtime at construction. Apps build the UI,
then runtime.run_forever().
ColorTheme(pal)
Semantic color theme for pdwidgets.
The default palette is a friendly, slightly colorful "early color Mac" look: a soft warm-cream background, near-black ink, and a small set of muted pastel accents (slate blue, warm gold, soft coral) with warm greys for inactive states — chunky-but-clean rather than a saturated Material blue.
Colors are computed through pal.color565 so the display's byteswap is
respected. Widgets reference these slots by name, so re-skinning the whole
toolkit is a matter of assigning different values here (or after
construction via display.color_theme).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pal
|
Palette
|
A palette object from the |
required |
Display(display_drv, runtime, tfa=0, bfa=0, format=RGB565)
Bases: Widget
Root display surface that owns the framebuffer, event loop, and widget tree.
Construct with a board display_drv and eventsys.Runtime. The runtime
drives input dispatch and periodic :meth:tick rendering; apps call
runtime.run_forever() after building the UI.
Initialize a Display object to manage the display and child widgets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
display_drv
|
DisplayDriver
|
The display driver object that manages the display hardware. |
required |
runtime
|
Runtime
|
The event runtime object that manages the event system. |
required |
tfa
|
int
|
The top fixed area of the display. |
0
|
bfa
|
int
|
The bottom fixed area of the display. |
0
|
format
|
int
|
The color format of the display (default is RGB565). |
RGB565
|
Usage
from board_config import display_drv, runtime display = Display(display_drv, runtime)
active_screen
property
writable
The currently attached :class:Screen, if any.
color_theme
property
Semantic color theme for this display.
display
property
Return self.
height
property
Framebuffer height in pixels.
parent
property
writable
Always None; the display is the root.
visible
property
writable
Always True.
width
property
Framebuffer width in pixels.
x
property
Display x offset (always 0).
y
property
Display y offset (always 0).
add_child(screen)
Set :attr:active_screen to screen.
add_task(callback, delay)
Schedule a repeating task run from :meth:tick.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
callback
|
callable
|
Zero-argument callable to run. |
required |
delay
|
int
|
Interval between runs, in milliseconds. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Task |
Task
|
The created task (pass to :meth: |
clip_pop()
Pop the current clip rectangle and restore the previous draw target.
clip_push(area)
Push an integer clip rectangle for nested draw/render (MCU-safe, no alpha).
handle_event(event, condition=None, point=None)
Dispatch an event, honoring modal pointer capture and focus keys.
Focus keys (Tab / Shift-Tab / arrows) are handled by
:attr:focus_manager before the widget tree walk. Pointer modality
(see :meth:Widget.set_modal) only affects mouse/touch — key focus is
independent so sheets/dialogs can still host TextInput fields.
quit()
Remove this display from the active list (called on QUIT).
refresh(area)
Copy a dirty region from the internal framebuffer to the physical display.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
area
|
Area
|
|
required |
remove_task(task)
Cancel a scheduled task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task
|
Task
|
A task previously returned by :meth: |
required |
render_dirty_widgets()
Redraw all invalidated widgets, breadth-first, without recursion.
set_position(*args, **kwargs)
Reset geometry to the full display size.
tick()
Render one widget frame.
Flushes dirty areas to the display, otherwise runs scheduled tasks and
re-renders invalidated widgets. Driven automatically by the runtime's
shared timer (see :meth:_attach_to_runtime); may also be called
manually (e.g. :func:tick) to force a frame.
IconTheme(path)
A class to manage icon themes. The path is the directory where the icons are stored. Icon file names are in the format "icon_name_18dp.pbm" where 18dp is the size of the icon. Valid sizes are in the ICON_SIZE enumeration, which are 18, 24, 36, and 48 pixels.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
The path to the directory containing the icon files. |
required |
Usage
from pdwidgets import IconTheme, ICON_SIZE icon_theme = IconTheme("/path/to/icons/") ... icon_button = IconButton(screen, icon_file=icon_theme.home(ICON_SIZE.LARGE), ...)
Screen(parent, fg=None, bg=None, visible=True)
Bases: Widget
Full-screen container for a page of widgets.
Initialize a Screen object to contain widgets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parent
|
Display
|
The display object that contains the screen. |
required |
fg
|
int
|
The foreground color of the screen. |
None
|
bg
|
int
|
The background color of the screen. |
None
|
visible
|
bool
|
The visibility of the screen. |
True
|
Usage
screen = Screen(display)
Task(callback, delay)
A task that runs a callback function after a specified delay. Used by the Display object to run tasks at regular intervals, such as refreshing the display or updating the clock.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
callback
|
callable
|
The function to run. |
required |
delay
|
int
|
The delay in milliseconds before running the callback. |
required |
Usage
def my_callback(): print("Hello, world!")
task = Task(my_callback, 1000) # Run my_callback every second display.add_task(task)
run(t)
Run the callback function and set the next run time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
t
|
int
|
The current time in milliseconds. |
required |
Widget(parent, x=0, y=0, w=None, h=None, align=None, align_to=None, fg=None, bg=None, visible=True, value=None, padding=None)
Base class for all pdwidgets UI elements.
Subclass :class:Widget for custom controls, or use it as a simple
container. Geometry uses relative x/y plus an :data:ALIGN
constant; :attr:value changes trigger :meth:changed and redraw via
:meth:invalidate. Pointer events route through :meth:handle_event;
use :meth:add_event_cb to register handlers.
The base Widget class for creating widgets. May be used as a base class for custom widgets or as a container for other widgets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parent
|
Widget
|
The parent widget that contains this widget. All widgets except the Display widget must have a parent. |
required |
x
|
int
|
The x-coordinate of the widget. |
0
|
y
|
int
|
The y-coordinate of the widget. |
0
|
w
|
int
|
The width of the widget. |
None
|
h
|
int
|
The height of the widget. |
None
|
align
|
int
|
The alignment of the widget (default is ALIGN.TOP_LEFT). |
None
|
align_to
|
Widget
|
The widget to align to (default is the parent widget). |
None
|
fg
|
int
|
The foreground color of the widget (default is the parent's foreground color). |
None
|
bg
|
int
|
The background color of the widget (default is the parent's background color). |
None
|
visible
|
bool
|
The visibility of the widget (default is True). |
True
|
value
|
str
|
The value of the widget (e.g., text of a label, value of a slider). |
None
|
padding
|
tuple
|
The padding on each side of the widget (default is (2, 2, 2, 2)). |
None
|
align
property
writable
Alignment constant from :data:ALIGN.
align_to
property
writable
Widget used as the alignment anchor.
area
property
Absolute bounding box of the widget on screen.
Returns:
| Name | Type | Description |
|---|---|---|
Area |
Area
|
|
color_theme
property
Semantic color palette from the display.
display
property
Root :class:Display for this widget subtree.
height
property
writable
Widget height in pixels.
padded_area
property
Bounding box inset by :attr:padding.
parent
property
writable
Parent widget that contains this widget.
value
property
writable
Widget value (text, number, bool, etc.).
visible
property
writable
Get widget visibility.
width
property
writable
Widget width in pixels.
x
property
writable
Calculate the absolute x-coordinate of the widget based on align
y
property
writable
Calculate the absolute y-coordinate of the widget based on align
add_child(child)
Adds a child widget to the current widget.
add_dirty_descendant(branch)
Bubble a dirty descendant up the tree.
add_dirty_widget(child)
Mark a direct child as dirty for rendering.
add_event_cb(event_type, callback, data=None)
Register a callback for an event type on this widget.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
|
required | |
callback
|
Callable invoked as |
required | |
data
|
User data passed to callback; defaults to this widget. |
None
|
changed()
Called when the value of the widget changes. May be overridden in subclasses. If overridden, the subclass should call this method to trigger the on_change_callback and invalidate.
draw(area=None)
Draw the widget on the screen. Subclasses should override this method to draw the widget unless the widget is a container widget (like a screen) that contains other widgets. Subclasses may call this method to draw the background of the widget before drawing other elements.
handle_event(event, condition=None, point=None)
Handle an event and propagate it to child widgets.
Subclasses that need to handle events should override this method and call it to propagate the event to children.
The default condition is a module-level function (not a per-call
closure), and for pointer events the pointer is translated to display
coordinates once per dispatch rather than once per child.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
Event
|
The event to handle. |
required |
condition
|
callable
|
|
None
|
point
|
tuple
|
Pre-translated pointer position, shared across the recursion for pointer events. |
None
|
hide(hide=True)
Show or hide the widget.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hide
|
bool
|
|
True
|
invalidate()
Mark this widget (and its descendants) as needing a redraw.
remove_child(widget)
Removes a child widget from the current widget.
remove_dirty_descendant(branch)
Clear a descendant branch from the dirty set.
remove_dirty_widget(child)
Clear a child from the dirty set.
remove_event_cb(event_type, callback)
Remove a previously registered event callback.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
int
|
|
required |
callback
|
callable
|
The callback to remove. No error if absent. |
required |
render()
Redraw this widget if invalidated, then clear its dirty flags.
set_change_cb(callback)
Set the callback invoked when the widget's value changes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
callback
|
callable
|
Called as |
required |
set_modal(modal=True)
Grab or release modal pointer capture for this widget.
While a widget is modal, the :class:Display routes all pointer events
(mouse/touch) through this widget's branch only, so widgets elsewhere in
the tree do not receive them. Non-pointer events (e.g. key events) are
unaffected. This is used by :class:Dialog and :class:Dropdown to
implement modal overlays without a separate event layer. Modality nests:
the most recently grabbed widget wins, and releasing restores the
previous one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modal
|
bool
|
|
True
|
set_position(x=None, y=None, w=None, h=None, align=None, align_to=None)
Update any subset of the widget's geometry and re-layout.
Only the arguments that are not None are changed. Changing geometry
invalidates the parent so the affected area is redrawn.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
int
|
New relative x-coordinate. |
None
|
y
|
int
|
New relative y-coordinate. |
None
|
w
|
int
|
New width. |
None
|
h
|
int
|
New height. |
None
|
align
|
int
|
New |
None
|
align_to
|
Widget
|
New widget to align against. |
None
|
set_value(value)
Set the widget's value (equivalent to assigning widget.value).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
The new value; triggers |
required |
tick(_=None)
Call the tick method of every registered :class:Display.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
_
|
Any
|
Ignored positional argument so this may also be used as a
timer/ |
None
|