Skip to content

0.3 feature: Checkbox, RadioGroup and ProgressBar - #13

Merged
Times0 merged 5 commits into
masterfrom
feature/choices
Oct 28, 2026
Merged

Times0 merged 5 commits into
masterfrom
feature/choices

Conversation

@Times0

@Times0 Times0 commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner

Stacked on #12

Summary

  • Checkbox(text="", *, value=False, on_change=None, color, text_color, font=None): a box with an antialiased check mark and an optional label to its right. It reuses _Clickable from button.py, so press and release, focus loss, hover, the hand cursor and the enabled/visible guards behave exactly like buttons. Clicking the box or the label toggles value and calls on_change(value). Setting value doesn't call it.
  • RadioGroup(options, *, index=0, on_change=None, direction="vertical", spacing=10, color, text_color, font=None): one widget that draws every option, stacked or in a row. value/index work like Dropdown: the setters validate and don't call on_change. highlighted is the hovered option. rect covers all options, but only the option rows are clickable or hoverable, so the gaps between them aren't.
  • ProgressBar(value=0.0, *, max_value=1.0, color, track_color, border_radius=None, show_text=False, font=None, text_color): display only (no events, no cursor). value is clamped, and fraction and percent_text are provided. draw(surface, x, y, width=200, height=12). border_radius=None gives pill ends. The fill is drawn as the full track shape clipped to the filled width, so a small value keeps a rounded left end and doesn't turn into a sliver.
  • New modules choice.py (Checkbox, RadioGroup) and progress.py, exported at the top level. All three follow the enabled/visible pattern: guards, _reset() clears press and hover, _paint() greys them out.
  • utils.draw_rounded_rect(surface, color, rect, radius, *, outline_color=None, outline_width=1) draws a filled rect with antialiased corners (quarter aacircles) and an optional outline. Button, Dropdown (box, menu, highlighted row), TextInput, Slider, the IconButton backdrop, the Dropdown shadow, the new widgets and the demo cards all use it in place of pg.draw.rect(border_radius=...), whose corners came out jagged. TextInput now draws straight onto the target surface with a clip, with no per-frame SRCALPHA surface. Cost: about 40 µs for an outlined button, and the demo frame went from about 1.2 to 2.6 ms with the dummy driver; it fills three bands rather than two overlapping rects, because SDL fill time grows with the row count.
  • Demo: a Checkbox and RadioGroup card. "Animate chart" stays in sync with the IconToggle, which shows that setters don't fire callbacks. "Show values" switches the chart to value labels. A horizontal RadioGroup sets the bar speed. A ProgressBar card has a looping "Loading" bar and a bar that follows the Integer slider. The States card also toggles the new widgets. The BarChart now spans one column over two rows. Callbacks are logged. The window is 1200×860 (was 1100×800). Screenshot regenerated.
  • README widget reference and CHANGELOG (Unreleased) updated.

Breaking changes

None. Only additions.

Deviations

  • No ProgressBar.update(dt) animation. Without a group or an update call the bar would never reach its value, so it's not trivial. Skipped as the brief allowed.
  • ProgressBar also takes text_color (needed for show_text, same as Slider).

How tested

  • New tests: Checkbox toggles by clicking the box and the label, ignores clicks outside, and its setter doesn't fire. A checkbox without text is square. RadioGroup selects by clicking a label or a circle; re-selecting or press-here-release-there doesn't fire; gaps aren't hit; hover highlight; horizontal layout. Index and value setters don't fire; bad index, value, direction, spacing and empty options are rejected before joining a group. ProgressBar: clamping, fraction (including after lowering max_value), percent_text, fill and track pixels, ignores events, validation. Disabled or hidden Checkbox and RadioGroup ignore clicks (directly and through a Group) and clear press and hover. The new widgets are added to the shared default-font, clickable and hidden/disabled drawing tests. Demo test: the checkboxes and radio drive the chart and are logged; the progress bars follow the loop and the slider.
  • Removing the interactive guard or the _reset override makes the new disabled tests fail.
  • uv run ruff check . && uv run ruff format --check . && uv run pytest && uv run pygameuikit-demo --frames 5: 116 passed.
  • Checked the demo screenshot, the disabled and interaction states, and a close-up of normal, hover, pressed and disabled states by eye.

@Times0
Times0 changed the base branch from feature/states to master October 28, 2026 10:24
@Times0
Times0 merged commit 8b0fedc into master Oct 28, 2026
9 checks passed
@Times0
Times0 deleted the feature/choices branch October 28, 2026 10:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant