Skip to content

Instantly share code, notes, and snippets.

@israel-dryer
Created April 16, 2021 13:42
Show Gist options
  • Save israel-dryer/f2d1db6f831da32937c16287d97e5cc8 to your computer and use it in GitHub Desktop.
Save israel-dryer/f2d1db6f831da32937c16287d97e5cc8 to your computer and use it in GitHub Desktop.
A simple example of creating a new ttk theme
"""
Author: Israel Dryer
Modified: 2021-04-16
Here's a simple example of creating a new theme with a single custom widget - a modern looking radiobutton.
In this example, I used a dictionary of settings. However, you can just as well do it with the Style.map,
Style.layout, and Style.configure methods. But, if you're going to build an entire theme, then using a settings
dictionary is more scalable, and could technically be stored in an offline json file as well.
"""
from PIL import ImageDraw, Image, ImageTk
from tkinter import ttk
style = ttk.Style()
# radio off image
radio_off = Image.new('RGBA', (134, 134))
draw = ImageDraw.Draw(radio_off)
draw.ellipse([2, 2, 132, 132], outline="#adb5bd", width=3, fill="#f8f9fa")
radio_off_img = ImageTk.PhotoImage(radio_off.resize((14, 14), Image.LANCZOS))
# radio on image
radio_on = Image.new('RGBA', (134, 134))
draw = ImageDraw.Draw(radio_on)
draw.ellipse([2, 2, 132, 132], outline="#4582ec", width=12, fill="#4582ec")
draw.ellipse([40, 40, 94, 94], fill="#ffffff")
radio_on_img = ImageTk.PhotoImage(radio_on.resize((14, 14), Image.LANCZOS))
# radio disabled image
radio_disabled = Image.new('RGBA', (134, 134))
draw = ImageDraw.Draw(radio_disabled)
draw.ellipse([2, 2, 132, 132], outline="#c5c7c7", width=3, fill="#f8f9fa")
draw.ellipse([40, 40, 94, 94], fill="#f8f9fa")
radio_disabled_img = ImageTk.PhotoImage(radio_disabled.resize((14, 14), Image.LANCZOS))
# create theme settings
theme_settings = {
'Radiobutton.indicator': {
'element create': ('image', radio_on_img,
('disabled', radio_disabled_img),
('!selected', radio_off_img),
{'width': 28, 'border': 4, 'sticky': 'w'})},
'TRadiobutton': {
'layout': [
('Radiobutton.padding', {'children': [
('primary.Radiobutton.indicator', {'side': 'left', 'sticky': ''}),
('Radiobutton.focus', {'children': [
('Radiobutton.label', {'sticky': 'nswe'})], 'side': 'left', 'sticky': ''})],
'sticky': 'nswe'})],
'configure': {
'background': "#ffffff",
'foreground': "#343a40",
'focuscolor': ''},
'map': {
'background': [
('active', '#ffffff')],
'foreground': [
('disabled', "#c5c7c7"),
('active !disabled', "#4582ec")]}}}
# create and apply custom theme
style.theme_create('myawesometheme', 'clam', theme_settings)
style.theme_use('myawesometheme')
# set the background to white (too lazy to create a frame)
style.master.configure(background="#ffffff")
# add the new widgets that I created
ttk.Radiobutton(text='option 1 - selected', value=1).pack(fill='x', padx=20, pady=(20, 2))
ttk.Radiobutton(text='option 2', value=2).pack(fill='x', padx=20, pady=2)
ttk.Radiobutton(text='option 3', value=3).pack(fill='x', padx=20, pady=2)
ttk.Radiobutton(text='option 4 - disabled', value=4, state='disabled').pack(fill='x', padx=20, pady=(2, 20))
style.master.mainloop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment