Repository navigation
0.3 cleanup 2/4: Button, ImageButton, IconButton, IconToggle and Label - #9
Merged
Merged
Conversation
A shared _Clickable base handles press-and-release-inside clicks, focus loss, the hand cursor and the consumed-event return value. Button draws a rounded rect with hover/pressed shades derived from its color, sizes itself to a Label (or a fixed width with align) and has a settable text property. ImageButton merges ButtonImage and ButtonImageText, IconButton replaces ButtonPngIcon and IconToggle replaces ButtonTwoStates with on_change(value). ButtonRect and the ButtonThread* classes are removed. Label now takes (text, color="white", *, font, align), draws exactly at (x, y) and aligns within an optional draw width; TextAlignment and bounding_rect are gone. Constructors validate before joining a group. ComboBox subclasses Button with minimal changes until it is rewritten.
This was referenced Oct 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #8.
Summary
Second of four stacked PRs for the 0.3.0 cleanup: buttons and label.
button.pynow has four classes on one small private base,_Clickable(Widget): a click is a left press and a release both inside the button, window focus loss cancels it,handle_eventreturns True when consumed, and the cursor is the hand.pressedreplacesclicked, and theon_clickattribute replacesonclick_f/connect().Button(text, on_click=None, *, color, text_color=None, border_radius=6, outline_color=None, padding=(16, 8), font=None, width=None, align="center"): draws a rounded rect directly withpg.draw.rect. The hover and pressed shades come fromcolorviautils.shade. Text is black or white viautils.best_contrast_colorunlesstext_coloris set. It sizes itself to itsLabelunlesswidthis given.textis a settable property that resizes the button.ImageButton(image, on_click=None, *, hover_image=None, text="", text_color="white", font=None): merges ButtonImage and ButtonImageText. Text is centered.IconButton(image, on_click=None, *, hover_color, hover_alpha=128, padding=6, border_radius=6): replaces ButtonPngIcon. It shows a translucent backdrop on hover, stronger while pressed. The clickable area is the icon plus padding, starting at (x, y).IconToggle(image_off, image_on, on_change=None, *, value=False, ...): replaces ButtonTwoStates.on_change(value: bool)gets the new value; settingvaluedoesn't fire it.Label(text, color="white", *, font=None, align="left")draws exactly at (x, y) with no hidden 10 px offset.draw(surface, x, y, width=None)aligns withinwidth. Settingtext/colorre-renders only on change.TextAlignmentandbounding_rectare removed, andalignis validated.Widget.__init__, so a bad widget never joins a group.utils: newshade(color, amount).best_contrast_colornow uses perceived brightness and returns apg.Color.make_surface_darkeris removed because nothing uses it anymore.ComboBoxnow subclassesButton. The changes are minimal; it gets rewritten asDropdownin the next PR.Button), README snippet and widget list, and CHANGELOG upgrade notes are updated.Breaking changes
Everything is in CHANGELOG.md under "Upgrading from 0.2", with an old → new mapping for every removed button class. For the ButtonThread* classes, the replacement is to set
button.textfrom your own state each frame. Labels lose their implicit 10 px padding, and IconButton draws the icon at (x + padding, y + padding).How tested
uv run ruff check . && uv run ruff format --check . && uv run pytest && uv run pygameuikit-demo --frames 5passes (58 tests). The old button/label tests are replaced with tests for:on_click) across all four classeson_change(value)and silent programmaticvalueButton.textresizing, fixedwidthI also rendered the button states, outlines, alignments, icon hover/pressed, toggle on/off and Label alignments headlessly and inspected the image.