Python TUI framework with mouse support, modular widget system, customizable and rapid terminal markup language and more
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
PyTermGUI's widget system provides a comprehensive set of UI components built on a hierarchical class structure. All widgets inherit from the base Widget class and support styling, event handling, focus management, and serialization.
The foundational widget class that provides core functionality for all UI components including styling, positioning, event handling, and focus management.
class Widget:
"""Base widget class with core functionality."""
def __init__(self, **attrs):
"""
Initialize widget with attributes.
Parameters:
- width (int, optional): Widget width
- height (int, optional): Widget height
- pos (tuple[int, int], optional): Position (x, y)
- id (str, optional): Unique widget identifier
- parent_align (HorizontalAlignment, optional): Alignment within parent
"""
@property
def width(self) -> int: ...
@property
def height(self) -> int: ...
@property
def pos(self) -> tuple[int, int]: ...
def handle_key(self, key: str) -> bool:
"""Handle keyboard input. Returns True if handled."""
def handle_mouse(self, event: MouseEvent) -> bool:
"""Handle mouse events. Returns True if handled."""
def get_lines(self) -> list[str]:
"""Get widget's rendered lines."""
def set_style(self, key: str, value: str):
"""Set widget style property."""
def serialize(self) -> dict:
"""Serialize widget state."""Text display widget supporting markup formatting and alignment options.
class Label(Widget):
"""Text display widget with markup support."""
def __init__(self, value: str = "", **attrs):
"""
Create label widget.
Parameters:
- value (str): Text content with optional markup
- parent_align (HorizontalAlignment, optional): Text alignment
"""
@property
def value(self) -> str: ...
@value.setter
def value(self, text: str): ...Layout widget that arranges child widgets vertically with scrolling support and automatic sizing.
class Container(Widget):
"""Vertical container widget with scrolling."""
def __init__(self, *widgets, **attrs):
"""
Create container with child widgets.
Parameters:
- widgets: Child widgets to add
- width (int, optional): Container width, defaults to 40
- box (str, optional): Border style ("SINGLE", "DOUBLE", etc.)
- centered_axis (CenteringPolicy, optional): Widget centering
"""
def add(self, widget) -> Widget:
"""Add widget to container."""
def remove(self, widget) -> Widget:
"""Remove widget from container."""
@property
def widgets(self) -> list[Widget]: ...
@property
def selected_index(self) -> int: ...
def select(self, index: int):
"""Select widget by index."""
def center(self, where: CenteringPolicy = None):
"""Center container contents."""Horizontal layout widget that arranges widgets side-by-side with configurable spacing.
class Splitter(Widget):
"""Horizontal widget container."""
def __init__(self, *widgets, **attrs):
"""
Create horizontal splitter.
Parameters:
- widgets: Child widgets to arrange horizontally
- separator (str, optional): String between widgets
"""
def add(self, widget, run_get_lines: bool = True) -> Widget:
"""Add widget to splitter."""Interactive button widget with click handling and customizable appearance.
class Button(Widget):
"""Interactive button widget."""
def __init__(self, label: str = "Button", onclick: Callable = None,
padding: int = 0, centered: bool = False, **attrs):
"""
Create button widget.
Parameters:
- label (str): Button text, defaults to "Button"
- onclick (callable, optional): Click handler function
- padding (int): Button padding, defaults to 0
- centered (bool): Whether button text is centered, defaults to False
"""
@property
def label(self) -> str: ...
def set_char(self, key: str, char: str):
"""Set button border character."""Text input widget with cursor support, validation, and completion capabilities.
class InputField(Widget):
"""Text input widget with cursor."""
def __init__(self, value: str = "", prompt: str = "", **attrs):
"""
Create input field.
Parameters:
- value (str): Initial text value
- prompt (str): Input prompt text
- validator (callable, optional): Input validation function
"""
@property
def value(self) -> str: ...
@value.setter
def value(self, text: str): ...
def clear(self):
"""Clear input field."""
def submit(self) -> str:
"""Submit input and return value."""Boolean checkbox widget with customizable checked/unchecked states.
class Checkbox(Widget):
"""Boolean checkbox widget."""
def __init__(self, onclick: Callable = None, checked: bool = False, **attrs):
"""
Create checkbox widget.
Parameters:
- onclick (callable, optional): Change handler
- checked (bool): Initial checked state
"""
@property
def checked(self) -> bool: ...
@checked.setter
def checked(self, state: bool): ...
def toggle(self):
"""Toggle checkbox state."""Toggle switch widget with customizable labels for on/off states.
class Toggle(Widget):
"""Toggle switch widget."""
def __init__(self, labels: tuple[str, str], onclick: Callable = None, **attrs):
"""
Create toggle widget.
Parameters:
- labels (tuple): (off_label, on_label) text pair
- onclick (callable, optional): Change handler
"""
@property
def toggled(self) -> bool: ...
def toggle(self):
"""Toggle switch state."""Numeric value slider widget with customizable range and step size.
class Slider(Widget):
"""Numeric value slider widget."""
def __init__(self, value: float = 0.0, **attrs):
"""
Create slider widget.
Parameters:
- value (float): Initial value
- min_value (float, optional): Minimum value
- max_value (float, optional): Maximum value
- step (float, optional): Step increment
"""
@property
def value(self) -> float: ...
@value.setter
def value(self, val: float): ...Color selection widget with palette display and color preview.
class ColorPicker(Widget):
"""Color selection widget."""
def __init__(self, **attrs):
"""Create color picker widget."""
@property
def color(self) -> Color: ...
def set_color(self, color: Color):
"""Set selected color."""Expandable/collapsible container section with toggle control.
class Collapsible(Container):
"""Collapsible container section."""
def __init__(self, title: str, *widgets, **attrs):
"""
Create collapsible section.
Parameters:
- title (str): Section header text
- widgets: Child widgets to contain
- collapsed (bool, optional): Initial collapsed state
"""
@property
def collapsed(self) -> bool: ...
def toggle(self):
"""Toggle collapsed state."""
def expand(self):
"""Expand section."""
def collapse(self):
"""Collapse section."""Pixel-based graphics widget for creating simple graphics and visualizations.
class PixelMatrix(Widget):
"""Pixel-based graphics widget."""
def __init__(self, width: int, height: int, **attrs):
"""
Create pixel matrix.
Parameters:
- width (int): Matrix width in pixels
- height (int): Matrix height in pixels
"""
def set_pixel(self, x: int, y: int, color: Color):
"""Set individual pixel color."""
def clear(self):
"""Clear all pixels."""
class DensePixelMatrix(PixelMatrix):
"""High-density pixel matrix widget."""Visual representation of keyboard keys for interface elements.
class KeyboardButton(Widget):
"""Keyboard key representation widget."""
def __init__(self, key: str, **attrs):
"""
Create keyboard button.
Parameters:
- key (str): Key name or symbol
"""Utility function for creating widgets from data structures.
def auto(data, **widget_args) -> Widget | list[Widget] | None:
"""
Create widgets from data structures.
Parameters:
- data: Input data (str, list, dict, tuple, etc.)
- widget_args: Additional widget attributes
Returns:
Widget instance(s) or None if conversion failed
Conversions:
- str -> Label
- list [label, onclick] -> Button
- list [bool, onclick] -> Checkbox
- tuple -> Splitter
- dict -> prompt Splitter pairs
"""Border and styling system for wrapping widgets with decorative frames.
class Frame:
"""Border frame that wraps around parent widgets."""
def __init__(self, parent: Widget):
"""
Create frame for widget.
Parameters:
- parent (Widget): Widget to wrap with frame
"""
@property
def borders(self) -> tuple[str, str, str, str]:
"""Get border characters (left, top, right, bottom)."""
@property
def corners(self) -> tuple[str, str, str, str]:
"""Get corner characters (left_top, right_top, right_bottom, left_bottom)."""
# Frame style constants
ASCII: type[Frame]
ASCII_X: type[Frame]
ASCII_O: type[Frame]
Light: type[Frame]
Heavy: type[Frame]
Double: type[Frame]
Rounded: type[Frame]
Frameless: type[Frame]
Padded: type[Frame]Additional specialized widget classes for enhanced functionality.
class FancyReprWidget(Widget):
"""Widget for displaying objects with fancy representation protocol."""
def __init__(self, target, starts_at: int = 0, **attrs):
"""
Create fancy repr widget.
Parameters:
- target: Object supporting __fancy_repr__ protocol
- starts_at (int): Starting line offset for display
"""
def inline(widget: Widget, *, exit_on: list[str] = None, width: int = None) -> Widget:
"""
Run widget as inline terminal prompt.
Parameters:
- widget (Widget): Widget to run inline
- exit_on (list, optional): Keys to exit on
- width (int, optional): Display width override
Returns:
The widget after inline execution
"""Global widget ID management functions.
def get_widget(widget_id: str) -> Widget | None:
"""Get widget by ID."""
def get_id(widget: Widget) -> str | None:
"""Get widget's ID."""import pytermgui as ptg
# Create a form-like layout
container = ptg.Container(
"[bold]User Information",
"",
ptg.Splitter(
ptg.Label("[72]Name:"),
ptg.InputField(placeholder="Enter name")
),
ptg.Splitter(
ptg.Label("[72]Email:"),
ptg.InputField(placeholder="Enter email")
),
"",
ptg.Checkbox(checked=True, label="Subscribe to newsletter"),
"",
ptg.Button("Submit", lambda btn: print("Form submitted")),
width=50
)# Using the auto() function for rapid prototyping
form = ptg.Container() + [
"[157 bold]Registration Form",
"",
{"[72]Username:": ptg.InputField()},
{"[72]Password:": ptg.InputField()},
"",
[True, lambda btn: print("Remember me toggled")], # Checkbox
"",
["Register", lambda btn: print("Registered")] # Button
]Install with Tessl CLI
npx tessl i tessl/pypi-pytermgui