Source code for mytk.radiobutton

"""radiobutton.py — A myTk wrapper for ttk.Radiobutton with group linking and observation.

This module defines a `RadioButton` class that wraps a `ttk.Radiobutton` widget
and provides a convenience method `linked_group()` to create a group of radio buttons
that share a common value variable (`IntVar`), ensuring mutual exclusivity.

Key Features:

- Radio buttons created via ``linked_group()`` share a ``value_variable``,
  enabling coordinated selection.
- Supports optional user callbacks triggered when selection changes.
- Observes variable changes even when updated programmatically, not just on click.

Example::

    def on_radio_change(button):
        print("Selected:", button.value)

    radios = RadioButton.linked_group(
        {"Option A": 1, "Option B": 2, "Option C": 3},
        user_callback=on_radio_change,
    )
"""

from tkinter import IntVar, ttk

from .base import Base


[docs] class RadioButton(Base): """A bindable wrapper around ttk.Radiobutton. Provides: - Optional user callback on selection change - Support for shared `IntVar` across multiple radio buttons - Observability for programmatic value changes """
[docs] @classmethod def linked_group(cls, labels_values, user_callback=None): """Creates a group of mutually exclusive radio buttons that share the same value variable. Args: labels_values (dict[str, int]): Dictionary mapping labels to integer values. user_callback (Callable, optional): Function called when any radio button is selected. Returns: list[RadioButton]: List of configured radio buttons sharing the same `IntVar`. """ radios = [] common_value_variable = IntVar() for label, value in labels_values.items(): radio = RadioButton(label, value, user_callback) radio.value_variable = common_value_variable radios.append(radio) return radios
def __init__(self, label, value, user_callback=None): """Initializes a single radio button. Args: label (str): The text label for the button. value (int): The integer value assigned to this button within the group. user_callback (Callable, optional): Function to call on selection. """ super().__init__() self.label = label self.value = value self.user_callback = user_callback
[docs] def create_widget(self, master, **kwargs): """Creates the ttk.Radiobutton widget and binds it to the value variable. Args: master (tk.Widget): The parent container. **kwargs: Additional keyword arguments. """ self.widget = ttk.Radiobutton( master, text=self.label, value=self.value, command=self.value_changed, ) self.bind_variable(self.value_variable)
[docs] def value_changed(self): """Invoke the user-defined callback when the radio button is selected.""" if self.user_callback is not None: try: self.user_callback(self) except Exception as err: raise RuntimeError("Unable complete callback") from err
[docs] def bind_variable(self, variable): """Binds the radio button to a shared IntVar and sets up an observer for changes. Notes: The `command` callback of a Radiobutton is only triggered by user clicks. To observe programmatic changes, this method also sets up observation. Args: variable (tk.IntVar): The shared value variable for this radio group. """ super().bind_variable(variable) self.add_observer(self, "value_variable", context="radiobutton-changed")
[docs] def observed_property_changed( self, observed_object, observed_property_name, new_value, context ): """Handles updates to the shared variable even when changed programmatically. Args: observed_object: The object being observed (usually self). observed_property_name (str): Name of the property being observed. new_value: The new value assigned. context (str): Context string used to identify the observer type. """ super().observed_property_changed( observed_object, observed_property_name, new_value, context ) if context == "radiobutton-changed": self.value_changed()