Tkinter ttkbootstrap Labelframe Widget Tutorial

The ttkbootstrap Labelframe widget extends standard Tkinter container frames by adding a labeled title border and theme-aware color palettes (`bootstyle`) to group related form controls cleanly.

Tutorial Breakdown:

Part I: Basic Labelframe Container Setup & Bootstyle Colors

ttkbootstrap Labelframe Basic We grouped widgets inside containers and used Pack layout manager.
Labelframe supports bootstyle=PRIMARY and bootstyle=SUCCESS to color-code border frames.

import ttkbootstrap as ttk
from ttkbootstrap.constants import *

app = ttk.Window(title="Labelframe Bootstyle Demo", themename="flatly")
app.geometry("420x260")

# Labelframe container with primary bootstyle border
lf = ttk.Labelframe(app, text="User Login Credentials", padding=20, bootstyle=PRIMARY)
lf.pack(padx=20, pady=20, fill=BOTH, expand=True)

lbl_user = ttk.Label(lf, text="Username: admin_user", font=("Helvetica", 10))
lbl_user.pack(anchor="w", pady=5)

lbl_role = ttk.Label(lf, text="Access Level: Superuser", font=("Helvetica", 10), bootstyle=SUCCESS)
lbl_role.pack(anchor="w", pady=5)

app.mainloop()
Practical Overview

The ttkbootstrap Labelframe component groups related controls into distinct bordered sections with descriptive header titles. Applying bootstyle attributes (such as PRIMARY or SUCCESS) highlights the frame border using theme-consistent colors.

Part II: Live Dynamic Theme Switcher

ttkbootstrap Labelframe Theme Switcher We used StringVar to track active themes and used Grid layout manager.
Selecting theme radio buttons triggers live style updates across container frames via app.style.theme_use().

import ttkbootstrap as ttk
from ttkbootstrap.constants import *

def change_theme():
    selected_theme = theme_var.get()
    app.style.theme_use(selected_theme)
    label_info.config(text=f"Active Theme: {selected_theme}")

app = ttk.Window(title="Labelframe Theme Switcher", themename="superhero")
app.geometry("460x300")

theme_var = ttk.StringVar(value="superhero")
themes = ["cosmo", "flatly", "superhero", "darkly"]

lbl_title = ttk.Label(app, text="Select Application Theme:", font=("Helvetica", 11, "bold"))
lbl_title.grid(row=0, column=0, columnspan=4, padx=15, pady=10, sticky="w")

for idx, t_name in enumerate(themes):
    rb = ttk.Radiobutton(
        app,
        text=t_name.capitalize(),
        value=t_name,
        variable=theme_var,
        command=change_theme,
        bootstyle="outline-toolbutton"
    )
    rb.grid(row=1, column=idx, padx=5, pady=5)

lf_widget = ttk.Labelframe(app, text="Container Panel", padding=15, bootstyle=WARNING)
lf_widget.grid(row=2, column=0, columnspan=4, padx=15, pady=15, sticky="ew")

lbl_inner = ttk.Label(lf_widget, text="Frame adjusts dynamically to active theme palette.", font=("Helvetica", 10))
lbl_inner.pack(anchor="w")

label_info = ttk.Label(app, text="Active Theme: superhero", bootstyle=SUCCESS, font=("Helvetica", 10))
label_info.grid(row=3, column=0, columnspan=4, padx=15, pady=5)

app.mainloop()

Part III: SQLite Database Integration (Saving Container Title & State)

ttkbootstrap Labelframe Database Integration We used SQLite database and SQLAlchemy to persist panel properties.
Upon startup, the Labelframe loads its header title directly from database records.

1️⃣ Creating SQLite Table & Inserting Container Record

from sqlalchemy import create_engine, text

# Use raw strings r"..." to prevent Unicode escape errors in Windows paths
DATABASE_URL = r"sqlite:///I:\My Drive\testing3\ttkbootstrap\containers_db.db"
engine = create_engine(DATABASE_URL, echo=False)

with engine.connect() as connection:
    connection.execute(text("CREATE TABLE IF NOT EXISTS frames (id INTEGER PRIMARY KEY, frame_key TEXT UNIQUE NOT NULL, frame_title TEXT NOT NULL)"))
    
    result = connection.execute(text("SELECT COUNT(*) FROM frames WHERE frame_key='main_panel'"))
    if result.scalar() == 0:
        connection.execute(text("INSERT INTO frames (frame_key, frame_title) VALUES ('main_panel', 'Authorized Personnel Portal')"))
        connection.commit()

print("Containers database initial setup completed.")

2️⃣ Dynamic GUI Rendering Labelframe Title from SQLite via SQLAlchemy

import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from sqlalchemy import create_engine, text

DATABASE_URL = r"sqlite:///I:\My Drive\testing3\ttkbootstrap\containers_db.db"
engine = create_engine(DATABASE_URL, echo=False)
connection = engine.connect()

def get_stored_title():
    res = connection.execute(text("SELECT frame_title FROM frames WHERE frame_key='main_panel'"))
    row = res.fetchone()
    return row[0] if row else "Default Panel"

root = ttk.Window(title="Labelframe SQLite Sync", themename="flatly")
root.geometry("440x240")

panel_title = get_stored_title()

lf_db = ttk.Labelframe(root, text=panel_title, padding=20, bootstyle=SUCCESS)
lf_db.pack(padx=20, pady=20, fill=BOTH, expand=True)

lbl_info = ttk.Label(lf_db, text="Labelframe title loaded successfully from SQLite.", font=("Helvetica", 10), bootstyle=INFO)
lbl_info.pack(anchor="w")

root.mainloop()
connection.close()

Part IV: Connecting to MySQL using SQLAlchemy

To connect your Labelframe database application to a centralized MySQL database server, update the SQLAlchemy connection string:

# SQLite Connection (Commented Out)
# DATABASE_URL = r"sqlite:///I:\My Drive	esting3	tkbootstrap\containers_db.db"

# MySQL Connection string using PyMySQL
DATABASE_URL = "mysql+pymysql://username:password@localhost/student_db"

engine = create_engine(DATABASE_URL, echo=False)

Common Errors & Troubleshooting

Issue / Error Cause Recommended Solution
Child widgets overflow outside Labelframe Using absolute positioning (`place`) or failing to apply expansion flags inside the frame. Use pack(fill=BOTH, expand=True) or grid() configuration for children inside the frame container.
Bootstyle border color not rendering Failing to pass the correct bootstyle constant or string identifier. Ensure bootstyle keyword is correctly assigned, e.g., bootstyle=PRIMARY or bootstyle="success".

Frequently Asked Questions

Use the labelanchor parameter (e.g., labelanchor="n", "ne", "e", "se", "s", "sw", "w", "nw") during initialization.

Yes! Pass integer padding values to the padding option (e.g., padding=15 or tuple padding like padding=(10, 5)).



Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer