ttkbootstrap is a powerful library that enhances Tkinter by providing modern UI themes. This tutorial demonstrates how to create and apply a custom theme in ttkbootstrap, enabling you to modify styles according to your application's requirements.
To define a custom theme, we use a JSON file containing color, font, and layout settings. Here is a sample JSON file, apply it, and use it to style widgets like Labels and Buttons.
{
"name": "mytheme",
"type": "dark",
"colors": {
"primary": "#1f3d7a",
"secondary": "#00aaff",
"success": "#28a745",
"info": "#FF6103",
"warning": "#ffc107",
"danger": "#dc3545",
"light": "#f8f9fa",
"dark": "#343a40",
"bg": "#121212",
"fg": "#e0e0e0",
"selectbg": "#444444",
"selectfg": "#ffffff"
}
}
# Import required libraries
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from ttkbootstrap.style import ThemeDefinition
import json # Load theme from a JSON file
# Load the custom theme JSON file
theme_path = "E:\\testing\\my_custom_theme.json" # Update with your file path
with open(theme_path, "r") as f:
custom_theme_data = json.load(f) # Load JSON as a dictionary
# Required theme properties
required_keys = ["name", "colors", "fonts", "layout"]
filtered_theme_data = {key: custom_theme_data[key] for key in required_keys if key in custom_theme_data}
# Ensure essential color properties exist
required_colors = ["border", "inputfg", "inputbg", "active"]
for color in required_colors:
if color not in filtered_theme_data["colors"]:
filtered_theme_data["colors"][color] = "#000000" # Default black if missing
# Convert dictionary to ThemeDefinition object
custom_theme = ThemeDefinition(**filtered_theme_data)
# Initialize ttkbootstrap style
style = ttk.Style()
style.register_theme(custom_theme) # Register theme
style.theme_use(custom_theme.name) # Apply theme
# Create main window
my_w = ttk.Window()
my_w.geometry("500x300") # Width and height
my_w.title("www.plus2net.com : ttkbootstrap custom theme")
# Label with custom theme
label = ttk.Label(my_w, text="Hello, Custom Theme!", bootstyle="info")
label.pack(pady=20)
# Button with theme styling
button = ttk.Button(my_w, text="Click Me", bootstyle="primary",
command=lambda: label.config(text="Button Clicked!"))
button.pack()
# Run the application
my_w.mainloop()
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from ttkbootstrap.style import ThemeDefinition
import json
# Load the custom theme JSON file
theme_path = "E:\\testing\\my_custom_theme.json" # Update the correct file path
with open(theme_path, "r") as f:
custom_theme_data = json.load(f) # Load JSON data into a dictionary
# Extract and validate required theme properties
required_keys = ["name", "colors", "fonts", "layout"]
filtered_theme_data = {key: custom_theme_data[key] for key in required_keys if key in custom_theme_data}
# Ensure the 'colors' dictionary has all required fields for a valid theme
required_colors = ["border", "inputfg", "inputbg", "active"]
for color in required_colors:
if color not in filtered_theme_data["colors"]:
filtered_theme_data["colors"][color] = "#000000" # Default to black if missing
# Convert the dictionary into a ThemeDefinition object
custom_theme = ThemeDefinition(**filtered_theme_data)
# Create the main window with the custom theme
my_w = ttk.Window()
my_w.geometry("500x300") # Set window dimensions (width x height)
my_w.title("www.plus2net.com : ttkbootstrap Custom Theme") # Set window title
# Initialize the style, register, and apply the custom theme
style = ttk.Style()
style.register_theme(custom_theme) # Register the theme
style.theme_use(custom_theme.name) # Apply the custom theme
# Create a Label Widget with custom theme styling
label = ttk.Label(my_w, text="Hello, Custom Theme!", bootstyle="info")
label.pack(pady=20) # Add vertical spacing
# Create a Button Widget styled with the custom theme
button = ttk.Button(
my_w, text="Click Me", bootstyle="primary",
command=lambda: label.config(text="Button Clicked!") # Change label text on click
)
button.pack()
# Run the main event loop
my_w.mainloop()
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from ttkbootstrap.style import ThemeDefinition
import json
# Load the custom theme JSON file
theme_path = "F:\\testing\\my_custom_theme.json" # update the path
with open(theme_path, "r") as f:
custom_theme_data = json.load(f) # Load JSON as a dictionary
# Extract and validate required theme properties
required_keys = ["name", "colors", "fonts", "layout"]
filtered_theme_data = {key: custom_theme_data[key] for key in required_keys if key in custom_theme_data}
# Ensure the 'colors' dictionary has all required fields
required_colors = ["border", "inputfg", "inputbg", "active"]
for color in required_colors:
if color not in filtered_theme_data["colors"]:
filtered_theme_data["colors"][color] = "#000000" # Default black if missing
# Convert the dictionary to a ThemeDefinition object
custom_theme = ThemeDefinition(**filtered_theme_data)
# Create the main window
my_w = ttk.Window()
my_w.geometry("500x300") # Width and height
my_w.title("www.plus2net.com : ttkbootstrap custom theme") # Adding a title
# Register and apply the custom theme
style = ttk.Style()
style.register_theme(custom_theme)
style.theme_use(custom_theme.name)
# Configure grid layout
my_w.columnconfigure(0, weight=1)
my_w.columnconfigure(1, weight=1)
my_w.rowconfigure(0, weight=1)
my_w.rowconfigure(1, weight=1)
# Add an Interactive Meter Widget
meter = ttk.Meter(
my_w,
bootstyle="success",
interactive=True,
amountused=40,
amounttotal=100,
subtext="Interactive Meter"
)
meter.grid(row=0, column=0, padx=10, pady=10)
# Add a Floodgauge Widget
fg = ttk.Floodgauge(
my_w,
bootstyle="info",
mask="Progress {}%",
variable=meter.amountusedvar, # Link Meter and Floodgauge
maximum=100,
length=200
)
fg.grid(row=0, column=1, padx=10, pady=10)
# Button to Start Floodgauge Animation
def start_gauge():
fg.start() # Start Floodgauge animation
btn = ttk.Button(my_w, text="Start Gauge", bootstyle="primary", command=start_gauge)
btn.grid(row=1, column=0, columnspan=2, pady=10)
# Label
label = ttk.Label(my_w, text="Welcome to My Custom Theme", bootstyle="info")
label.grid(row=2, column=0, columnspan=2, pady=10)
my_w.mainloop()
TTK Creator is a GUI tool that allows users to design and customize themes for ttkbootstrap. With an intuitive interface, users can adjust colors, styles, and widget appearances to create personalized themes for Tkinter applications.
To use TTK Creator, install ttkbootstrap if you haven't already:
pip install ttkbootstrap
Run the following command in your terminal or command prompt:
python -m ttkcreator
This will open the graphical interface where you can modify and preview themes.
user.py
C:\Users\YourUsername\.ttkbootstrap\themes\
(Windows)
or ~/.ttkbootstrap/themes/
(Linux/macOS).themename
when initializing ttk.Window
.import ttkbootstrap as ttk
root = ttk.Window(themename="my_theme_v1")
root.mainloop()
With TTK Creator, you can effortlessly enhance the appearance of your Tkinter applications with custom themes!
While JSON files are commonly used to store UI theme settings, using a database like SQLite or MySQL provides more flexibility and scalability. A database allows dynamic updates, centralized storage, and multi-user access without modifying static files. By fetching theme settings directly from a database, we can easily switch themes, customize UI elements, and even allow users to personalize their application interface in real time. 🚀
import os
from sqlalchemy import create_engine, text
# 🔹 Define Database Path (Same Directory)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DB_PATH = os.path.join(BASE_DIR, "theme.db")
# 🔹 Create Database Engine
engine = create_engine(f"sqlite:///{DB_PATH}")
# engine = create_engine("mysql+pymysql://username:password@localhost/theme_db") # MySQL Connection
# 🔹 Create Themes Table
with engine.connect() as conn:
conn.execute(text("""
CREATE TABLE IF NOT EXISTS themes (
name TEXT PRIMARY KEY,
primary_color TEXT,
secondary_color TEXT,
font_family TEXT,
font_size INTEGER
)
"""))
conn.commit()
# 🔹 Sample Theme Data (Multiple Themes)
themes = [
("dark_theme", "#343A40", "#6C757D", "Arial", 12),
("light_theme", "#F8F9FA", "#E9ECEF", "Calibri", 11),
("custom_theme", "#007BFF", "#6C757D", "Helvetica", 10)
]
# 🔹 Insert Theme Data (Avoid Duplicate Entries)
with engine.connect() as conn:
for theme in themes:
conn.execute(text("DELETE FROM themes WHERE name = :name"), {"name": theme[0]})
conn.execute(text("INSERT INTO themes VALUES (:name, :primary, :secondary, :font, :size)"),
{"name": theme[0], "primary": theme[1], "secondary": theme[2], "font": theme[3], "size": theme[4]})
conn.commit()
print("✅ Themes inserted successfully!")
Here is the code to to create one simple application using above database. Note that both files are to be kept in same directory as we are using os module to read the path and apply the same.
import os
from sqlalchemy import create_engine, text
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
# 🔹 Define Database Path (Same Directory)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DB_PATH = os.path.join(BASE_DIR, "theme.db")
# 🔹 Create Database Engine
engine = create_engine(f"sqlite:///{DB_PATH}") # SQLite Connection
# engine = create_engine("mysql+pymysql://username:password@localhost/theme_db") # MySQL Connection
# 🔹 Fetch Theme Data (Select Theme Name Here)
theme_name = "custom_theme" # Change to "dark_theme" or "light_theme"
with engine.connect() as conn:
result = conn.execute(text("SELECT * FROM themes WHERE name = :name"), {"name": theme_name}).fetchone()
# 🔹 If Theme Exists, Apply It
if result:
theme_name, primary_color, secondary_color, font_family, font_size = result
# 🔹 Create Main Window
my_w = ttk.Window()
my_w.geometry("400x200")
my_w.title("www.plus2net.com : SQLite Theme Example")
# 🔹 Apply Custom Theme
style = ttk.Style()
style.configure("TButton", font=(font_family, font_size), background=primary_color)
style.configure("TLabel", font=(font_family, font_size), background=secondary_color)
# 🔹 Create Label
label = ttk.Label(my_w, text="Hello, Custom Theme!", bootstyle="info")
label.pack(pady=20)
# 🔹 Create Button
button = ttk.Button(my_w, text="Click Me", bootstyle="primary",
command=lambda: label.config(text="Button Clicked!"))
button.pack()
my_w.mainloop()
else:
print("❌ No theme data found in database.")
In this tutorial, we learned how to:
By following these steps, you can customize the look and feel of your Tkinter applications effortlessly!
Learn More on ttkbootstrap