Skip to main content

A GUI framework built on Pygame. Designed as a retained-mode UI system with a component tree, extensible widgets, and focus management.

Project description

pygame-widget-kit

PyPI

A GUI framework built on Pygame. pygame-widget-kit is a retained-mode UI system with a component tree, event routing, focus and modal management, and extensible widgets such as Select/Dropdown and TextInput with mouse-based text selection and clipboard support.

PyPI: https://pypi.org/project/pygame-widget-kit/

Features

  • Retained-mode component tree with nested children
  • Event routing with hover, focus, and active state handling
  • Modal/dropdown support via UIManager
  • Built-in widgets: Button, Text, Select, Radio, TextInput
  • Text input filtering modes (text, number, hex, binary, octal)
  • Clipboard copy/paste in TextInput (requires pygame.scrap)

Installation

pip install pygame-widget-kit

Pygame is listed as a dependency (pygame >= 2.0.0). Make sure you call pygame.init() before creating widgets.

Usage

import pygame
from pygame_widget_kit import *


SCREEN_WIDTH = 900
SCREEN_HEIGHT = 720


def update_label_from_input(input_box: TextInput, label: Text):
    label.set_text(f"Label: {input_box.text_value}")


def update_select_label(select: Select, label: Text):
    label.set_text(f"Selected: {select.selected_value}")


def main():
    pygame.init()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    clock = pygame.time.Clock()

    root = Widget((0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), border_color=None)
    ui = UIManager(root)

    title = Text("pygame-widget-kit demo", pos=(24, 20), text_color=(0, 0, 0))
    root.add_child(title)

    input_box = TextInput(rect=(24, 70, 220, 36), initial_text="")
    update_button = Button("Update label", pos=(256, 70), size=(160, 36))
    value_label = Text("Label: (empty)", pos=(432, 76), text_color=(0, 0, 0))
    update_button.click_bind(update_label_from_input, input_box, value_label)

    root.add_child(input_box)
    root.add_child(update_button)
    root.add_child(value_label)

    input_types_title = Text("input types:", pos=(24, 150), text_color=(0, 0, 0))
    root.add_child(input_types_title)

    input_rows = [
        ("Allow all:", ALLOW_ALL_CHARS),
        ("Text only:", TEXT_ONLY),
        ("Number only:", NUMBER_ONLY),
        ("Hex only:", HEX_ONLY),
        ("Binary only:", BINARY_ONLY),
    ]

    input_label_x = 24
    input_box_x = 200
    input_row_y = 190
    input_row_gap = 44

    for index, (label_text, mode) in enumerate(input_rows):
        row_y = input_row_y + index * input_row_gap
        row_label = Text(label_text, pos=(input_label_x, row_y + 6), text_color=(0, 0, 0))
        row_input = TextInput(rect=(input_box_x, row_y, 240, 34), allowed_char_mode=mode)
        root.add_child(row_label)
        root.add_child(row_input)

    select_label = Text("Select:", pos=(24, 430), text_color=(0, 0, 0))
    select = Select(
        rect=(100, 424, 160, 32),
        options=["Easy", "Hard", "Expert"],
        default_index=0,
        z_index=2
    )
    select_value = Text("Selected: Easy", pos=(280, 430), text_color=(0, 0, 0))
    select.bind_on_option_chance(update_select_label, select, select_value)

    root.add_child(select_label)
    root.add_child(select)
    root.add_child(select_value)

    radio_label = Text("Radio:", pos=(24, 490), text_color=(0, 0, 0))
    radio = Radio(
        (100, 486, 150, 28),
        options=["OPTION A","OPTION B","OPTION C"],
        default_index=0,
    )
    radio_value = Text("Radio: A", pos=(280, 490), text_color=(0, 0, 0))

    root.add_child(radio_label)
    root.add_child(radio)
    root.add_child(radio_value)

    radio_last_value = radio.get_value()

    running = True
    while running:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            ui.handle_event(event)

        current_radio_value = radio.get_value()
        if current_radio_value != radio_last_value:
            radio_value.set_text(f"Radio: {current_radio_value}")
            radio_last_value = current_radio_value

        screen.fill((250, 250, 250))
        root.draw(screen)
        pygame.display.flip()

    pygame.quit()


if __name__ == "__main__":
    main()

Usage notes

  • Use UIManager to handle events and manage focus/active state.
  • Call root.add_child(...) to build a component tree. Child positions are relative to their parent.
  • TextInput handles caret blink in draw, so you only need to call draw each frame.
  • Select uses modal behavior through UIManager; clicks outside the dropdown close it.
  • Select expects options as a list of strings and exposes selected_value.
  • Radio expects options as a list of (label, value) tuples and exposes get_value().

TextInput allowed_char_mode

  • ALLOW_ALL_CHARS
  • TEXT_ONLY
  • NUMBER_ONLY
  • HEX_ONLY
  • BINARY_ONLY
  • OCTAL_ONLY

Creating custom widgets

Subclass UIComponent and override any of the following hooks:

  • draw(surface) for custom rendering
  • handle_event(event) for keyboard/mouse logic
  • on_click(event) for click behavior

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pygame_widget_kit-0.0.2.tar.gz (12.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pygame_widget_kit-0.0.2-py3-none-any.whl (14.5 kB view details)

Uploaded Python 3

File details

Details for the file pygame_widget_kit-0.0.2.tar.gz.

File metadata

  • Download URL: pygame_widget_kit-0.0.2.tar.gz
  • Upload date:
  • Size: 12.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.12.4

File hashes

Hashes for pygame_widget_kit-0.0.2.tar.gz
Algorithm Hash digest
SHA256 7305ee1e52f2aa12d30e231c3d793bf444be1e1f4c609ed3b1a9161ffb5c7979
MD5 83055f6579b389d103b8db71c8943bb4
BLAKE2b-256 d87a02ec1e8a6ddc6a2bf8ba52507c5c55e2877576aecb60f70c19b6b7690994

See more details on using hashes here.

File details

Details for the file pygame_widget_kit-0.0.2-py3-none-any.whl.

File metadata

File hashes

Hashes for pygame_widget_kit-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 02c39b9cec2c27d36f22853d3fe280b23e2c568d806ac46da958a8cf0f66ea0e
MD5 38027c3455ab844c3ba587b0e3153608
BLAKE2b-256 f989bf3517ab40761262f145b643ee93c2c4b38f37fdb7379281403e6cf56288

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page