How to Use Tkinter Checkbutton in Python

If you need a yes/no option in a Python window, a Tkinter Checkbutton tied to a BooleanVar is the answer: the box toggles the variable, and var.get() tells you whether it’s checked.

agree = tk.BooleanVar()
tk.Checkbutton(root, text="I agree", variable=agree).pack()

Most people get stuck on reading the value, running code on a click, or a ttk box that starts half-checked.

In this tutorial, I’ll build a small checkout form step by step on Python 3.12.5 with Tk 8.6, with every window captured from a real run on Windows 11.

The sample Checkbutton data: checkout add-ons

Every example uses four add-ons from a bike shop checkout: a $49.99 helmet, $24.50 bike lights, a $35.00 U-lock and $5.00 gift wrap.

Method 1: Create a Tkinter Checkbutton with BooleanVar (Recommended)

Use this for a single on/off choice. Here’s the gift wrap option on its own, with a label that reports the state:

import tkinter as tk

root = tk.Tk()
root.title("Gift wrap")
root.geometry("400x150")

wrap = tk.BooleanVar(value=False)

def show_choice():
    status.config(text=f"Gift wrap selected: {wrap.get()}")

check = tk.Checkbutton(root, text="Add gift wrap ($5.00)",
                       variable=wrap, command=show_choice)
check.pack(pady=(24, 8))
status = tk.Label(root, text="Gift wrap selected: False")
status.pack()
root.mainloop()
Tkinter Checkbutton window before and after checking Add gift wrap, with a label showing Gift wrap selected True
Left: unchecked and False. Right: after one click the box is checked and the label says True.

How does this code work?

variable=wrap links the box to the BooleanVar, so a click flips it between False and True. An IntVar would hold 0 and 1.

command=show_choice runs after each click, once the variable already holds the new value. The guide to getting a Tkinter Checkbutton value covers IntVar and reading the value later.

Method 2: Run code when a Checkbutton is clicked

Same checkout form, now with all four add-ons. Each box gets its own BooleanVar in a dictionary, and every box calls one function that recalculates the total:

import tkinter as tk

ADDONS = {"Helmet": 49.99, "Bike lights": 24.50,
          "U-lock": 35.00, "Gift wrap": 5.00}

root = tk.Tk()
root.title("Checkout add-ons")
root.geometry("400x230")
choices = {}

def update_total():
    total = sum(price for name, price in ADDONS.items()
                if choices[name].get())
    total_label.config(text=f"Add-ons total: ${total:.2f}")

for name, price in ADDONS.items():
    choices[name] = tk.BooleanVar()
    tk.Checkbutton(root, text=f"{name} (${price:.2f})",
                   variable=choices[name],
                   command=update_total).pack(anchor="w", padx=20)

total_label = tk.Label(root, text="Add-ons total: $0.00")
total_label.pack(pady=12)
root.mainloop()
Tkinter window with four add-on Checkbuttons where Helmet and U-lock are checked and the total label shows $84.99
With the helmet and U-lock checked, the label shows an add-ons total of $84.99.

How does this code work?

The loop builds one Checkbutton per dictionary entry. update_total() sums only the prices whose variable is True: $49.99 + $35.00 = $84.99.

Important: pass the function itself, command=update_total, not update_total(). The same rule is explained in the Tkinter button command tutorial.

Method 3: Store custom values with onvalue and offvalue

Sometimes you want text instead of True/False, like a shipping code you’ll send to an API. Point the box at a StringVar and set onvalue and offvalue:

import tkinter as tk

root = tk.Tk()
shipping = tk.StringVar(value="standard")
fast = tk.Checkbutton(root, text="Express shipping",
                      variable=shipping,
                      onvalue="express", offvalue="standard")
fast.pack()

print("Start:", shipping.get())
fast.invoke()                 # same as a click
print("After a click:", shipping.get())
root.destroy()

Output:

Start: standard
After a click: express

The variable moved from standard to express after invoke(), which acts like a real click and also runs the command. select() and deselect() only change the state.

If only one choice in a group may be on, use a Tkinter Radiobutton instead.

How do I make a Tkinter Checkbutton checked by default?

Start the variable at tk.BooleanVar(value=True), or call check.select() after creating the box. More options are in the post on a Tkinter checkbox checked by default.

Method 4: Add a Select all Checkbutton in a grid

Same checkout form again, now in a two-column grid with a Select all box. It sets every variable, and each item box updates the Select all state:

import tkinter as tk

ADDONS = {"Helmet": 49.99, "Bike lights": 24.50,
          "U-lock": 35.00, "Gift wrap": 5.00}

root = tk.Tk()
root.title("Select all add-ons")
root.geometry("400x180")
choices = {name: tk.BooleanVar() for name in ADDONS}
all_var = tk.BooleanVar()

def refresh():
    picked = [n for n, v in choices.items() if v.get()]
    all_var.set(len(picked) == len(ADDONS))
    total = sum(ADDONS[n] for n in picked)
    summary.config(text=f"{len(picked)} selected, ${total:.2f}")

def toggle_all():
    for var in choices.values():
        var.set(all_var.get())
    refresh()

select_all = tk.Checkbutton(root, text="Select all",
                            variable=all_var, command=toggle_all)
select_all.grid(row=0, column=0, sticky="w", padx=16, pady=(12, 4))
for i, name in enumerate(ADDONS):
    tk.Checkbutton(root, text=name, variable=choices[name],
                   command=refresh).grid(row=1 + i // 2, column=i % 2,
                                         sticky="w", padx=(32, 8))
summary = tk.Label(root, text="0 selected, $0.00")
summary.grid(row=3, column=0, columnspan=2, sticky="w", padx=16, pady=12)
root.mainloop()
Tkinter window with a Select all Checkbutton checked, four add-ons checked in a grid, and a label reading 4 selected, $114.49
One click on Select all checks every add-on and the summary reads 4 selected, $114.49.

How does this code work?

toggle_all() copies the Select all value into every add-on variable. refresh() keeps Select all checked only while all four are picked.

Placing the boxes with row and column is covered in the Tkinter grid layout guide.

Style or disable a Checkbutton with ttk

ttk.Checkbutton follows the Windows theme, so it looks native. Here’s a delivery panel with a checked, a disabled and a variable-less box:

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
root.title("Delivery options")
root.geometry("400x150")

express = tk.BooleanVar(value=True)
ttk.Checkbutton(root, text="Express shipping ($12.00)",
                variable=express).pack(anchor="w", padx=20, pady=(16, 4))

gift = tk.BooleanVar()
wrap = ttk.Checkbutton(root, text="Gift wrap (sold out)", variable=gift)
wrap.state(["disabled"])
wrap.pack(anchor="w", padx=20, pady=4)

no_var = ttk.Checkbutton(root, text="Leave at the door")
no_var.pack(anchor="w", padx=20, pady=4)

root.mainloop()
Tkinter window with a checked ttk Checkbutton, a disabled gift wrap option and a ttk box in the alternate state
The sold-out gift wrap is grayed out, and the ttk box without a variable shows a dash instead of a check.

wrap.state(["disabled"]) grays the box out; on classic widgets use state="disabled". For fonts and colors on text near the boxes, see the Tkinter Label tutorial.

So here’s the catch: “Leave at the door” has no variable, so it starts in the alternate state (the dash).

Which Checkbutton method should you use?

NeedUse
One yes/no optionBooleanVar + variable=
React to every clickcommand=func
Text valuesonvalue / offvalue
Many optionsDict of variables + Select all
Native look or disabledttk.Checkbutton

Things to keep in mind with Tkinter Checkbuttons

  • Keep a reference to every variable; in my run, an inline tk.BooleanVar() was garbage-collected and showed the dash.
  • command isn’t called by var.set() or select(), only by clicks and invoke().
  • Give every ttk Checkbutton a variable to avoid the alternate dash.

Keep building the form with these next:

Frequently asked questions

How do I create a checkbox in Python Tkinter?

Use tk.Checkbutton(root, text="...", variable=var) with a BooleanVar, then pack() it.

How do I get the value of a Tkinter Checkbutton?

Call get() on its variable.

How do I run a function when a Checkbutton is clicked?

Pass command=func without parentheses.

How do I uncheck a Checkbutton from code?

Use var.set(False) or check.deselect(). Neither one calls the command.

Why does my ttk Checkbutton show a dash?

It has no variable. Pass variable=tk.BooleanVar().

Where is ttk.Checkbutton documented?

See ttk Checkbutton in the Python docs.