0
# Widget System
1
2
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.
3
4
## Capabilities
5
6
### Base Widget
7
8
The foundational widget class that provides core functionality for all UI components including styling, positioning, event handling, and focus management.
9
10
```python { .api }
11
class Widget:
12
"""Base widget class with core functionality."""
13
14
def __init__(self, **attrs):
15
"""
16
Initialize widget with attributes.
17
18
Parameters:
19
- width (int, optional): Widget width
20
- height (int, optional): Widget height
21
- pos (tuple[int, int], optional): Position (x, y)
22
- id (str, optional): Unique widget identifier
23
- parent_align (HorizontalAlignment, optional): Alignment within parent
24
"""
25
26
@property
27
def width(self) -> int: ...
28
29
@property
30
def height(self) -> int: ...
31
32
@property
33
def pos(self) -> tuple[int, int]: ...
34
35
def handle_key(self, key: str) -> bool:
36
"""Handle keyboard input. Returns True if handled."""
37
38
def handle_mouse(self, event: MouseEvent) -> bool:
39
"""Handle mouse events. Returns True if handled."""
40
41
def get_lines(self) -> list[str]:
42
"""Get widget's rendered lines."""
43
44
def set_style(self, key: str, value: str):
45
"""Set widget style property."""
46
47
def serialize(self) -> dict:
48
"""Serialize widget state."""
49
```
50
51
### Label
52
53
Text display widget supporting markup formatting and alignment options.
54
55
```python { .api }
56
class Label(Widget):
57
"""Text display widget with markup support."""
58
59
def __init__(self, value: str = "", **attrs):
60
"""
61
Create label widget.
62
63
Parameters:
64
- value (str): Text content with optional markup
65
- parent_align (HorizontalAlignment, optional): Text alignment
66
"""
67
68
@property
69
def value(self) -> str: ...
70
71
@value.setter
72
def value(self, text: str): ...
73
```
74
75
### Container
76
77
Layout widget that arranges child widgets vertically with scrolling support and automatic sizing.
78
79
```python { .api }
80
class Container(Widget):
81
"""Vertical container widget with scrolling."""
82
83
def __init__(self, *widgets, **attrs):
84
"""
85
Create container with child widgets.
86
87
Parameters:
88
- widgets: Child widgets to add
89
- width (int, optional): Container width, defaults to 40
90
- box (str, optional): Border style ("SINGLE", "DOUBLE", etc.)
91
- centered_axis (CenteringPolicy, optional): Widget centering
92
"""
93
94
def add(self, widget) -> Widget:
95
"""Add widget to container."""
96
97
def remove(self, widget) -> Widget:
98
"""Remove widget from container."""
99
100
@property
101
def widgets(self) -> list[Widget]: ...
102
103
@property
104
def selected_index(self) -> int: ...
105
106
def select(self, index: int):
107
"""Select widget by index."""
108
109
def center(self, where: CenteringPolicy = None):
110
"""Center container contents."""
111
```
112
113
### Splitter
114
115
Horizontal layout widget that arranges widgets side-by-side with configurable spacing.
116
117
```python { .api }
118
class Splitter(Widget):
119
"""Horizontal widget container."""
120
121
def __init__(self, *widgets, **attrs):
122
"""
123
Create horizontal splitter.
124
125
Parameters:
126
- widgets: Child widgets to arrange horizontally
127
- separator (str, optional): String between widgets
128
"""
129
130
def add(self, widget, run_get_lines: bool = True) -> Widget:
131
"""Add widget to splitter."""
132
```
133
134
### Button
135
136
Interactive button widget with click handling and customizable appearance.
137
138
```python { .api }
139
class Button(Widget):
140
"""Interactive button widget."""
141
142
def __init__(self, label: str = "Button", onclick: Callable = None,
143
padding: int = 0, centered: bool = False, **attrs):
144
"""
145
Create button widget.
146
147
Parameters:
148
- label (str): Button text, defaults to "Button"
149
- onclick (callable, optional): Click handler function
150
- padding (int): Button padding, defaults to 0
151
- centered (bool): Whether button text is centered, defaults to False
152
"""
153
154
@property
155
def label(self) -> str: ...
156
157
def set_char(self, key: str, char: str):
158
"""Set button border character."""
159
```
160
161
### InputField
162
163
Text input widget with cursor support, validation, and completion capabilities.
164
165
```python { .api }
166
class InputField(Widget):
167
"""Text input widget with cursor."""
168
169
def __init__(self, value: str = "", prompt: str = "", **attrs):
170
"""
171
Create input field.
172
173
Parameters:
174
- value (str): Initial text value
175
- prompt (str): Input prompt text
176
- validator (callable, optional): Input validation function
177
"""
178
179
@property
180
def value(self) -> str: ...
181
182
@value.setter
183
def value(self, text: str): ...
184
185
def clear(self):
186
"""Clear input field."""
187
188
def submit(self) -> str:
189
"""Submit input and return value."""
190
```
191
192
### Checkbox
193
194
Boolean checkbox widget with customizable checked/unchecked states.
195
196
```python { .api }
197
class Checkbox(Widget):
198
"""Boolean checkbox widget."""
199
200
def __init__(self, onclick: Callable = None, checked: bool = False, **attrs):
201
"""
202
Create checkbox widget.
203
204
Parameters:
205
- onclick (callable, optional): Change handler
206
- checked (bool): Initial checked state
207
"""
208
209
@property
210
def checked(self) -> bool: ...
211
212
@checked.setter
213
def checked(self, state: bool): ...
214
215
def toggle(self):
216
"""Toggle checkbox state."""
217
```
218
219
### Toggle
220
221
Toggle switch widget with customizable labels for on/off states.
222
223
```python { .api }
224
class Toggle(Widget):
225
"""Toggle switch widget."""
226
227
def __init__(self, labels: tuple[str, str], onclick: Callable = None, **attrs):
228
"""
229
Create toggle widget.
230
231
Parameters:
232
- labels (tuple): (off_label, on_label) text pair
233
- onclick (callable, optional): Change handler
234
"""
235
236
@property
237
def toggled(self) -> bool: ...
238
239
def toggle(self):
240
"""Toggle switch state."""
241
```
242
243
### Slider
244
245
Numeric value slider widget with customizable range and step size.
246
247
```python { .api }
248
class Slider(Widget):
249
"""Numeric value slider widget."""
250
251
def __init__(self, value: float = 0.0, **attrs):
252
"""
253
Create slider widget.
254
255
Parameters:
256
- value (float): Initial value
257
- min_value (float, optional): Minimum value
258
- max_value (float, optional): Maximum value
259
- step (float, optional): Step increment
260
"""
261
262
@property
263
def value(self) -> float: ...
264
265
@value.setter
266
def value(self, val: float): ...
267
```
268
269
### ColorPicker
270
271
Color selection widget with palette display and color preview.
272
273
```python { .api }
274
class ColorPicker(Widget):
275
"""Color selection widget."""
276
277
def __init__(self, **attrs):
278
"""Create color picker widget."""
279
280
@property
281
def color(self) -> Color: ...
282
283
def set_color(self, color: Color):
284
"""Set selected color."""
285
```
286
287
### Collapsible
288
289
Expandable/collapsible container section with toggle control.
290
291
```python { .api }
292
class Collapsible(Container):
293
"""Collapsible container section."""
294
295
def __init__(self, title: str, *widgets, **attrs):
296
"""
297
Create collapsible section.
298
299
Parameters:
300
- title (str): Section header text
301
- widgets: Child widgets to contain
302
- collapsed (bool, optional): Initial collapsed state
303
"""
304
305
@property
306
def collapsed(self) -> bool: ...
307
308
def toggle(self):
309
"""Toggle collapsed state."""
310
311
def expand(self):
312
"""Expand section."""
313
314
def collapse(self):
315
"""Collapse section."""
316
```
317
318
### PixelMatrix
319
320
Pixel-based graphics widget for creating simple graphics and visualizations.
321
322
```python { .api }
323
class PixelMatrix(Widget):
324
"""Pixel-based graphics widget."""
325
326
def __init__(self, width: int, height: int, **attrs):
327
"""
328
Create pixel matrix.
329
330
Parameters:
331
- width (int): Matrix width in pixels
332
- height (int): Matrix height in pixels
333
"""
334
335
def set_pixel(self, x: int, y: int, color: Color):
336
"""Set individual pixel color."""
337
338
def clear(self):
339
"""Clear all pixels."""
340
341
class DensePixelMatrix(PixelMatrix):
342
"""High-density pixel matrix widget."""
343
```
344
345
### KeyboardButton
346
347
Visual representation of keyboard keys for interface elements.
348
349
```python { .api }
350
class KeyboardButton(Widget):
351
"""Keyboard key representation widget."""
352
353
def __init__(self, key: str, **attrs):
354
"""
355
Create keyboard button.
356
357
Parameters:
358
- key (str): Key name or symbol
359
"""
360
```
361
362
### Widget Factory Function
363
364
Utility function for creating widgets from data structures.
365
366
```python { .api }
367
def auto(data, **widget_args) -> Widget | list[Widget] | None:
368
"""
369
Create widgets from data structures.
370
371
Parameters:
372
- data: Input data (str, list, dict, tuple, etc.)
373
- widget_args: Additional widget attributes
374
375
Returns:
376
Widget instance(s) or None if conversion failed
377
378
Conversions:
379
- str -> Label
380
- list [label, onclick] -> Button
381
- list [bool, onclick] -> Checkbox
382
- tuple -> Splitter
383
- dict -> prompt Splitter pairs
384
"""
385
```
386
387
### Frame System
388
389
Border and styling system for wrapping widgets with decorative frames.
390
391
```python { .api }
392
class Frame:
393
"""Border frame that wraps around parent widgets."""
394
395
def __init__(self, parent: Widget):
396
"""
397
Create frame for widget.
398
399
Parameters:
400
- parent (Widget): Widget to wrap with frame
401
"""
402
403
@property
404
def borders(self) -> tuple[str, str, str, str]:
405
"""Get border characters (left, top, right, bottom)."""
406
407
@property
408
def corners(self) -> tuple[str, str, str, str]:
409
"""Get corner characters (left_top, right_top, right_bottom, left_bottom)."""
410
411
# Frame style constants
412
ASCII: type[Frame]
413
ASCII_X: type[Frame]
414
ASCII_O: type[Frame]
415
Light: type[Frame]
416
Heavy: type[Frame]
417
Double: type[Frame]
418
Rounded: type[Frame]
419
Frameless: type[Frame]
420
Padded: type[Frame]
421
```
422
423
### Advanced Widgets
424
425
Additional specialized widget classes for enhanced functionality.
426
427
```python { .api }
428
class FancyReprWidget(Widget):
429
"""Widget for displaying objects with fancy representation protocol."""
430
431
def __init__(self, target, starts_at: int = 0, **attrs):
432
"""
433
Create fancy repr widget.
434
435
Parameters:
436
- target: Object supporting __fancy_repr__ protocol
437
- starts_at (int): Starting line offset for display
438
"""
439
440
def inline(widget: Widget, *, exit_on: list[str] = None, width: int = None) -> Widget:
441
"""
442
Run widget as inline terminal prompt.
443
444
Parameters:
445
- widget (Widget): Widget to run inline
446
- exit_on (list, optional): Keys to exit on
447
- width (int, optional): Display width override
448
449
Returns:
450
The widget after inline execution
451
"""
452
```
453
454
### Widget Management
455
456
Global widget ID management functions.
457
458
```python { .api }
459
def get_widget(widget_id: str) -> Widget | None:
460
"""Get widget by ID."""
461
462
def get_id(widget: Widget) -> str | None:
463
"""Get widget's ID."""
464
```
465
466
## Usage Examples
467
468
### Basic Container Layout
469
470
```python
471
import pytermgui as ptg
472
473
# Create a form-like layout
474
container = ptg.Container(
475
"[bold]User Information",
476
"",
477
ptg.Splitter(
478
ptg.Label("[72]Name:"),
479
ptg.InputField(placeholder="Enter name")
480
),
481
ptg.Splitter(
482
ptg.Label("[72]Email:"),
483
ptg.InputField(placeholder="Enter email")
484
),
485
"",
486
ptg.Checkbox(checked=True, label="Subscribe to newsletter"),
487
"",
488
ptg.Button("Submit", lambda btn: print("Form submitted")),
489
width=50
490
)
491
```
492
493
### Widget Auto-Creation
494
495
```python
496
# Using the auto() function for rapid prototyping
497
form = ptg.Container() + [
498
"[157 bold]Registration Form",
499
"",
500
{"[72]Username:": ptg.InputField()},
501
{"[72]Password:": ptg.InputField()},
502
"",
503
[True, lambda btn: print("Remember me toggled")], # Checkbox
504
"",
505
["Register", lambda btn: print("Registered")] # Button
506
]
507
```