Skip to content

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 palettes package; used only for its color565 conversion (and byteswap handling).

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:remove_task to cancel).

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

Area or (x, y, w, h) rectangle to flush.

required

remove_task(task)

Cancel a scheduled task.

Parameters:

Name Type Description Default
task Task

A task previously returned by :meth:add_task.

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

(x, y, width, height) in display coordinates.

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

eventsys.events constant (e.g. events.MOUSEBUTTONDOWN).

required
callback

Callable invoked as callback(event, data).

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

condition(child, event, point) returning True when the event should be delivered to child. Defaults to a pointer-hit test for mouse events, else always True.

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 to hide, False to show.

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

eventsys.events constant the callback was registered for.

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 callback(widget) on change.

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 to grab modal capture, False to release.

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 ALIGN constant.

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 changed when it differs.

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/on_tick callback signature.

None