tkinter checkbutton different image

Viewed 3472

I want a tkinter checkbutton that basically has my own images for on and off, so not the default checkbutton. I've searched the internet for a solution, but couldn't find anything. I'm thinking it might be possible with ttk styling, but i'm not sure how

tried changing the selectimage option in the checkbutton, which did absolutely nothing

edit: turning indicatoron to false, then changing image and selectimage works

2 Answers

You need to set the image option for the unselected state, and the selectimage option for the selected state. You also need to set indicatoron to False so that tkinter doesn't show the default indicator.

Here is a simple example:

import tkinter as tk
root = tk.Tk()

on_image = tk.PhotoImage(width=48, height=24)
off_image = tk.PhotoImage(width=48, height=24)
on_image.put(("green",), to=(0, 0, 23,23))
off_image.put(("red",), to=(24, 0, 47, 23))

var1 = tk.IntVar(value=1)
var2 = tk.IntVar(value=0)
cb1 = tk.Checkbutton(root, image=off_image, selectimage=on_image, indicatoron=False,
                     onvalue=1, offvalue=0, variable=var1)
cb2 = tk.Checkbutton(root, image=off_image, selectimage=on_image, indicatoron=False,
                     onvalue=1, offvalue=0, variable=var2)

cb1.pack(padx=20, pady=10)
cb2.pack(padx=20, pady=10)

root.mainloop()

screenshot

The ttk.Checkbutton widget has fewer options than the tk.Checkbutton widget. E.g. the options selectimage and indicatoron options are not available.

To achieve the same result as shown in the answer by @ByranOakley, the following was done:

import tkinter as tk
import tkinter.ttk as ttk

root = tk.Tk()
root['background'] = 'white'  # for linux distro

# Remove the indicator from a customised TCheckbutton style layout
s = ttk.Style()
s.layout('no_indicatoron.TCheckbutton',
         [('Checkbutton.padding', {'sticky': 'nswe', 'children': [
             # ('Checkbutton.indicator', {'side': 'left', 'sticky': ''}),
             ('Checkbutton.focus', {'side': 'left', 'sticky': 'w',
                                    'children':
                                    [('Checkbutton.label', {'sticky': 'nswe'})]})]})]
         )

on_image = tk.PhotoImage(width=48, height=24)
off_image = tk.PhotoImage(width=48, height=24)
on_image.put(("green",), to=(0, 0, 23, 23))
off_image.put(("red",), to=(24, 0, 47, 23))

var1 = tk.IntVar(value=1)
var2 = tk.IntVar(value=0)


# Define functions to check Checkbutton state to show the corrsponding image.
def cb1_state():
    if cb1.instate(['!disabled', 'selected']):
        cb1['image'] = on_image
        print(f'cb1-on_image {var1.get()}')
    else:
        cb1['image'] = off_image
        print(f'cb1-off_image {var2.get()}')
    print()


def cb2_state():
    if cb2.instate(['!disabled', 'selected']):
        cb2['image'] = on_image
        print(f'cb2-on_image {var2.get()}')
    else:
        cb2['image'] = off_image
        print(f'cb2-off_image {var2.get()}')
    print()


# Use the customised style and functions
cb1 = ttk.Checkbutton(root, image=off_image, onvalue=1, offvalue=0,
                      variable=var1, style='no_indicatoron.TCheckbutton',
                      command=cb1_state)
cb2 = ttk.Checkbutton(root, image=off_image, onvalue=1, offvalue=0,
                      variable=var2, style='no_indicatoron.TCheckbutton',
                      command=cb2_state)

cb1.pack(padx=20, pady=10)
cb2.pack(padx=20, pady=10)

root.mainloop()

picture

Related