Tkinter Designer

← tkinter how-to

How do I get the value of the selected Radiobutton in tkinter?

A Radiobutton has no idea the others exist. What groups them is a single Tk variable shared by every button in the group, each button carrying its own value — and you read the answer from that variable, never from the buttons.

import tkinter as tk

root = tk.Tk()

size = tk.StringVar(value="medium")      # the group *is* this variable

for label in ("small", "medium", "large"):
    tk.Radiobutton(root, text=label.title(), variable=size, value=label).pack(anchor="w")

def order():
    print("chose", size.get())           # read the variable, not the buttons

tk.Button(root, text="Order", command=order).pack()
root.mainloop()

Why every button looks selected at once

Two different mistakes produce it. The first is a fresh variable for each button, usually a tk.IntVar() created inside the loop that builds them. Every button then owns a group of one, and a group of one always shows its own selection, so they all fill in together.

The second is one shared variable but no value on the buttons. A Radiobutton with no value has the empty string as its value, so clicking any one of them sets the variable to the empty string, which is exactly what every other button is watching for. Each button needs a distinct value.

# wrong: a new variable per button, so each one is its own group
for i, label in enumerate(("small", "medium", "large")):
    v = tk.IntVar()
    tk.Radiobutton(root, text=label, variable=v, value=i).pack()

# wrong: shared variable, but every button has the same empty value
tk.Radiobutton(root, text="Small", variable=size).pack()
tk.Radiobutton(root, text="Large", variable=size).pack()

Why two unrelated groups fight each other

Leaving variable off altogether does not make the buttons independent, which is the assumption that makes this one so confusing. They all fall into a single group that Tk supplies by default, named selectedButton, so a size group and a payment group in the same window will deselect each other and look like tkinter forgetting the choice.

One variable per group is the whole of the fix. The variable is the group, so two groups means two variables, and every button has to name the one it belongs to.

size = tk.StringVar(value="medium")
payment = tk.StringVar(value="card")

tk.Radiobutton(root, text="Small",  variable=size,    value="small")
tk.Radiobutton(root, text="Large",  variable=size,    value="large")
tk.Radiobutton(root, text="Card",   variable=payment, value="card")
tk.Radiobutton(root, text="PayPal", variable=payment, value="paypal")

Reacting the moment they choose

A command runs on every click, after the variable has been updated, so it can call .get() straight away and act on the answer. This is how you show a price, enable a field, or swap part of the window as the choice changes.

Give every button in the group the same command. It receives no argument saying which button was clicked, and it does not need one, because the variable already holds the answer.

def on_choice():
    print("now", size.get())

tk.Radiobutton(root, text="Large", variable=size, value="large", command=on_choice)

Starting with nothing selected

Set the variable to a value no button uses. An empty StringVar does this on its own, which is the main reason a StringVar is easier here than an IntVar: tk.IntVar() starts at 0, so a button with a value of 0 comes up already selected whether you intended it or not.

The same move resets the group later. size.set("") clears the selection, and size.set("large") moves the dot from code without a click.

size = tk.StringVar()          # nothing selected to begin with
size.set("large")              # select Large from code
size.set("")                   # back to nothing selected

Strings or numbers as values

Either works, but the value is the thing your handler has to make sense of later, so a StringVar holding "large" reads better at the point of use than an IntVar holding 2 — and it survives someone reordering the buttons. Reach for numbers when the value is genuinely a number you are about to calculate with.

Doing it without the lookup

Drop the radio buttons on and give them the same Group (variable) name in the inspector, with a different Value on each. The export writes one StringVar per group name and wires every button in that group to it, so neither grouping mistake above is possible — two groups get two variables because they have two names.

Lay the window out visually and read the generated Python as you go.

Open the tkinter designer →

Related questions