A widget and grid based framework for building command line user interfaces in python.
—
Methods for creating and managing all widget types including scroll menus, text boxes, buttons, labels, and custom widgets. Includes widget positioning, removal, and focus management.
Scrollable menu widgets for displaying selectable lists of items.
def add_scroll_menu(title: str, row: int, column: int, row_span: int = 1,
column_span: int = 1, padx: int = 1, pady: int = 0) -> ScrollMenu:
"""
Add a scrollable menu widget to the grid.
Parameters:
- title: Widget title displayed in border
- row: Grid row position (0-indexed)
- column: Grid column position (0-indexed)
- row_span: Number of rows to span (default: 1)
- column_span: Number of columns to span (default: 1)
- padx: Horizontal padding in characters (default: 1)
- pady: Vertical padding in characters (default: 0)
Returns:
ScrollMenu widget instance
"""
class ScrollMenu:
def add_item(item: Any) -> None: ...
def add_item_list(item_list: List[Any]) -> None: ...
def remove_selected_item() -> None: ...
def remove_item(item: Any) -> None: ...
def get_item_list() -> List[Any]: ...
def get() -> Optional[Any]: ...
def get_selected_item() -> Optional[Any]: ...
def is_empty() -> bool: ...
def set_selected_item(selected_item: Any) -> None: ...
def get_selected_item_index() -> int: ...
def set_selected_item_index(selected_item_index: int) -> None: ...
def clear() -> None: ...
def set_on_selection_change_event(callback: Callable[[Any], Any]) -> None: ...Usage example:
root = py_cui.PyCUI(3, 3)
menu = root.add_scroll_menu('Options', 0, 0, row_span=2)
menu.add_item('Option 1')
menu.add_item('Option 2')
menu.add_item_list(['Option 3', 'Option 4', 'Option 5'])
def handle_selection():
selected = menu.get_selected_item()
print(f'Selected: {selected}')
menu.add_key_command(py_cui.keys.KEY_ENTER, handle_selection)Menu widgets with checkboxes for multiple selections.
def add_checkbox_menu(title: str, row: int, column: int, row_span: int = 1,
column_span: int = 1, padx: int = 1, pady: int = 0,
checked_char: str = "X") -> CheckBoxMenu:
"""
Add a checkbox menu widget to the grid.
Parameters:
- title: Widget title displayed in border
- row: Grid row position (0-indexed)
- column: Grid column position (0-indexed)
- row_span: Number of rows to span (default: 1)
- column_span: Number of columns to span (default: 1)
- padx: Horizontal padding in characters (default: 1)
- pady: Vertical padding in characters (default: 0)
- checked_char: Character to display for checked items (default: "X")
Returns:
CheckBoxMenu widget instance
"""
class CheckBoxMenu:
def add_item(text: str, checked: bool = False) -> None: ...
def add_item_list(item_list: List[str]) -> None: ...
def get_checked_items() -> List[str]: ...
def mark_item_as_checked(item_index: int) -> None: ...
def mark_item_as_unchecked(item_index: int) -> None: ...
def toggle_item_checked(item_index: int) -> None: ...Usage example:
root = py_cui.PyCUI(3, 3)
checkbox_menu = root.add_checkbox_menu('Features', 0, 1, checked_char='✓')
checkbox_menu.add_item('Feature A', True) # Initially checked
checkbox_menu.add_item('Feature B', False)
checkbox_menu.add_item_list(['Feature C', 'Feature D'])
def show_checked():
checked = checkbox_menu.get_checked_items()
print(f'Checked items: {checked}')
def toggle_current():
current_index = checkbox_menu.get_selected_item_index()
checkbox_menu.toggle_item_checked(current_index)
checkbox_menu.add_key_command(py_cui.keys.KEY_SPACE, toggle_current)Single-line text input widgets for user text entry.
def add_text_box(title: str, row: int, column: int, row_span: int = 1,
column_span: int = 1, padx: int = 1, pady: int = 0,
initial_text: str = "", password: bool = False) -> TextBox:
"""
Add a text input box widget to the grid.
Parameters:
- title: Widget title displayed in border
- row: Grid row position (0-indexed)
- column: Grid column position (0-indexed)
- row_span: Number of rows to span (default: 1)
- column_span: Number of columns to span (default: 1)
- padx: Horizontal padding in characters (default: 1)
- pady: Vertical padding in characters (default: 0)
- initial_text: Initial text content (default: "")
- password: If True, display '*' instead of characters (default: False)
Returns:
TextBox widget instance
"""
class TextBox:
def get() -> str: ...
def set_text(text: str) -> None: ...
def clear() -> None: ...
def write(text: str) -> None: ...Usage example:
root = py_cui.PyCUI(3, 3)
name_box = root.add_text_box('Name', 0, 0, initial_text='Enter name...')
password_box = root.add_text_box('Password', 1, 0, password=True)
def submit_form():
name = name_box.get()
password = password_box.get()
print(f'Name: {name}, Password: {"*" * len(password)}')
submit_btn = root.add_button('Submit', 2, 0, command=submit_form)Scrollable text block widgets for displaying multi-line text content.
def add_text_block(title: str, row: int, column: int, row_span: int = 1,
column_span: int = 1, padx: int = 1, pady: int = 0,
initial_text: str = "") -> ScrollTextBlock:
"""
Add a scrollable text block widget to the grid.
Parameters:
- title: Widget title displayed in border
- row: Grid row position (0-indexed)
- column: Grid column position (0-indexed)
- row_span: Number of rows to span (default: 1)
- column_span: Number of columns to span (default: 1)
- padx: Horizontal padding in characters (default: 1)
- pady: Vertical padding in characters (default: 0)
- initial_text: Initial text content (default: "")
Returns:
ScrollTextBlock widget instance
"""
class ScrollTextBlock:
def set_text(text: str) -> None: ...
def get_text() -> str: ...
def write(text: str) -> None: ...
def clear() -> None: ...
def scroll_up() -> None: ...
def scroll_down() -> None: ...Usage example:
root = py_cui.PyCUI(3, 3)
log_block = root.add_text_block('Log Output', 0, 0, row_span=3, column_span=2)
log_block.set_text('Application started...\nInitializing components...')
log_block.write('\nReady for input.')
# Add scroll controls
log_block.add_key_command(py_cui.keys.KEY_UP_ARROW, log_block.scroll_up)
log_block.add_key_command(py_cui.keys.KEY_DOWN_ARROW, log_block.scroll_down)Simple text labels for displaying static text.
def add_label(title: str, row: int, column: int, row_span: int = 1,
column_span: int = 1, padx: int = 1, pady: int = 0) -> Label:
"""
Add a simple label widget to the grid.
Parameters:
- title: Widget title and text content
- row: Grid row position (0-indexed)
- column: Grid column position (0-indexed)
- row_span: Number of rows to span (default: 1)
- column_span: Number of columns to span (default: 1)
- padx: Horizontal padding in characters (default: 1)
- pady: Vertical padding in characters (default: 0)
Returns:
Label widget instance
"""
def add_block_label(title: str, row: int, column: int, row_span: int = 1,
column_span: int = 1, padx: int = 1, pady: int = 0,
center: bool = True) -> BlockLabel:
"""
Add a block-style label widget to the grid.
Parameters:
- title: Widget title and text content
- row: Grid row position (0-indexed)
- column: Grid column position (0-indexed)
- row_span: Number of rows to span (default: 1)
- column_span: Number of columns to span (default: 1)
- padx: Horizontal padding in characters (default: 1)
- pady: Vertical padding in characters (default: 0)
- center: Whether to center the text (default: True)
Returns:
BlockLabel widget instance
"""
class Label:
def set_title(title: str) -> None: ...
def get_title() -> str: ...
class BlockLabel(Label):
def set_text(text: str) -> None: ...
def get_text() -> str: ...Usage example:
root = py_cui.PyCUI(3, 3)
header = root.add_block_label('Welcome to My App', 0, 0, column_span=3, center=True)
status = root.add_label('Status: Ready', 2, 0)
status.set_title('Status: Processing...')Clickable button widgets that execute commands when activated.
def add_button(title: str, row: int, column: int, row_span: int = 1,
column_span: int = 1, padx: int = 1, pady: int = 0,
command: Callable[[], Any] = None) -> Button:
"""
Add a button widget to the grid.
Parameters:
- title: Button text
- row: Grid row position (0-indexed)
- column: Grid column position (0-indexed)
- row_span: Number of rows to span (default: 1)
- column_span: Number of columns to span (default: 1)
- padx: Horizontal padding in characters (default: 1)
- pady: Vertical padding in characters (default: 0)
- command: Function to execute when button is pressed (optional)
Returns:
Button widget instance
"""
class Button:
def set_command(command: Callable[[], Any]) -> None: ...
def get_command() -> Callable[[], Any]: ...Usage example:
def save_data():
print('Saving data...')
def load_data():
print('Loading data...')
root = py_cui.PyCUI(3, 3)
save_btn = root.add_button('Save', 0, 0, command=save_data)
load_btn = root.add_button('Load', 0, 1, command=load_data)
# Change button command later
save_btn.set_command(lambda: print('Save with new logic'))Slider controls for numeric value selection.
def add_slider(title: str, row: int, column: int, row_span: int = 1,
column_span: int = 1, padx: int = 1, pady: int = 0,
min_val: int = 0, max_val: int = 100, step: int = 1,
init_val: int = 0) -> SliderWidget:
"""
Add a slider widget to the grid.
Parameters:
- title: Widget title displayed in border
- row: Grid row position (0-indexed)
- column: Grid column position (0-indexed)
- row_span: Number of rows to span (default: 1)
- column_span: Number of columns to span (default: 1)
- padx: Horizontal padding in characters (default: 1)
- pady: Vertical padding in characters (default: 0)
- min_val: Minimum slider value (default: 0)
- max_val: Maximum slider value (default: 100)
- step: Step size for value changes (default: 1)
- init_val: Initial slider value (default: 0)
Returns:
SliderWidget instance
"""
class SliderWidget:
def get_slider_value() -> float: ...
def update_slider_value(offset: int) -> float: ...
def set_slider_step(step: int) -> None: ...
def set_bar_char(char: str) -> None: ...
def toggle_title() -> None: ...
def toggle_border() -> None: ...
def toggle_value() -> None: ...
def align_to_top() -> None: ...Usage example:
root = py_cui.PyCUI(3, 3)
volume_slider = root.add_slider('Volume', 0, 0, min_val=0, max_val=100, init_val=50)
def update_volume():
volume = volume_slider.get_slider_value()
print(f'Volume set to: {volume}%')
volume_slider.add_key_command(py_cui.keys.KEY_ENTER, update_volume)System for adding custom widget types not included with py_cui by default.
def add_custom_widget(widget_class: type, title: str, row: int, column: int,
row_span: int, column_span: int, padx: int, pady: int,
*args, **kwargs) -> Widget:
"""
Add a custom widget type to the grid.
Parameters:
- widget_class: Custom widget class (must inherit from Widget)
- title: Widget title displayed in border
- row: Grid row position (0-indexed)
- column: Grid column position (0-indexed)
- row_span: Number of rows to span
- column_span: Number of columns to span
- padx: Horizontal padding in characters
- pady: Vertical padding in characters
- *args, **kwargs: Additional arguments passed to widget constructor
Returns:
Custom widget instance
Raises:
TypeError: If widget_class is not a subclass of Widget
"""Usage example:
import py_cui
class CustomProgressBar(py_cui.widgets.Widget):
def __init__(self, id, title, grid, row, col, row_span, col_span, padx, pady, logger, max_val=100):
super().__init__(id, title, grid, row, col, row_span, col_span, padx, pady, logger)
self.max_val = max_val
self.current_val = 0
def set_progress(self, value):
self.current_val = min(value, self.max_val)
root = py_cui.PyCUI(3, 3)
progress = root.add_custom_widget(CustomProgressBar, 'Progress', 0, 0, 1, 2, 1, 0, max_val=200)
progress.set_progress(75)Functions for managing widgets after creation including selection, focus, and removal.
def get_widgets() -> Dict[int, Optional[Widget]]:
"""
Get current set of widgets.
Returns:
Dictionary mapping widget IDs to widget instances
"""
def get_selected_widget() -> Optional[Widget]:
"""
Get currently selected widget.
Returns:
Currently selected widget instance or None
"""
def set_selected_widget(widget_id: int) -> None:
"""
Set the selected widget.
Parameters:
- widget_id: ID of widget to select
"""
def move_focus(widget: Widget, auto_press_buttons: bool = True) -> None:
"""
Move focus to specified widget.
Parameters:
- widget: Widget to focus on
- auto_press_buttons: Whether to auto-execute button commands (default: True)
"""
def lose_focus() -> None:
"""Exit focus mode and return to overview mode."""
def forget_widget(widget: Widget) -> None:
"""
Remove widget from the UI.
Parameters:
- widget: Widget to remove
Raises:
TypeError: If widget is not a Widget instance
KeyError: If widget does not exist in current UI
"""Usage example:
root = py_cui.PyCUI(3, 3)
menu = root.add_scroll_menu('Menu', 0, 0)
button = root.add_button('Focus Menu', 1, 0, command=lambda: root.move_focus(menu))
# Get all widgets
widgets = root.get_widgets()
print(f'Total widgets: {len([w for w in widgets.values() if w is not None])}')
# Remove widget
root.forget_widget(button)Install with Tessl CLI
npx tessl i tessl/pypi-py-cui