Tkinter ttkbootstrap Menubutton Widget Tutorial

The ttkbootstrap Menubutton widget combines a standard push button with a dropdown menu list, offering theme-aware color styling (`bootstyle`) for quick command triggers in GUI menus.

Tutorial Breakdown:

Part I: Basic Menubutton Setup & Menu Commands

ttkbootstrap Menubutton Basic We created dropdown action lists and used Pack layout manager.
Menubutton supports bootstyle=SUCCESS and attaches an inner Menu component.

import ttkbootstrap as ttk
from ttkbootstrap.constants import *

def set_action(choice):
    lbl_status.config(text=f"Executed Action: {choice}")

app = ttk.Window(title="Menubutton Demo", themename="flatly")
app.geometry("400x220")

# Menubutton with success bootstyle
mb = ttk.Menubutton(app, text="File Options", bootstyle=SUCCESS)
mb.pack(padx=20, pady=25)

# Attach Menu items
menu = ttk.Menu(mb, tearoff=0)
menu.add_command(label="New File", command=lambda: set_action("New File"))
menu.add_command(label="Open...", command=lambda: set_action("Open..."))
menu.add_separator()
menu.add_command(label="Save", command=lambda: set_action("Save"))

mb["menu"] = menu

lbl_status = ttk.Label(app, text="Executed Action: None", font=("Helvetica", 11, "bold"), bootstyle=INFO)
lbl_status.pack(padx=20, pady=10)

app.mainloop()
Practical Overview

The ttkbootstrap Menubutton presents a dropdown list of options when clicked. By pairing it with a standard Menu instance and assigning it via mb["menu"] = menu, developers can organize commands cleanly within toolbars or menus.

Part II: Live Dynamic Theme Switcher

ttkbootstrap Menubutton Theme Switcher We used StringVar to track themes and used Grid layout manager.
Selecting theme radio buttons triggers live style updates across the application 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="Menubutton Theme Switcher", themename="superhero")
app.geometry("460x260")

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)

mb_widget = ttk.Menubutton(app, text="Actions Menu", bootstyle=WARNING)
mb_widget.grid(row=2, column=0, columnspan=4, padx=15, pady=20)

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 Last Executed Action)

ttkbootstrap Menubutton Database Integration We used SQLite database and SQLAlchemy to persist the last performed menu action.
Upon startup, the application loads the previous action history from SQLite.

1️⃣ Creating SQLite Table & Inserting Default Log

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\actions_db.db"
engine = create_engine(DATABASE_URL, echo=False)

with engine.connect() as connection:
    connection.execute(text("CREATE TABLE IF NOT EXISTS action_log (id INTEGER PRIMARY KEY, log_key TEXT UNIQUE NOT NULL, last_action TEXT NOT NULL)"))
    
    result = connection.execute(text("SELECT COUNT(*) FROM action_log WHERE log_key='menu_state'"))
    if result.scalar() == 0:
        connection.execute(text("INSERT INTO action_log (log_key, last_action) VALUES ('menu_state', 'Initialized')"))
        connection.commit()

print("Action log database initial setup completed.")

2️⃣ Dynamic GUI Syncing Menubutton Actions with 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\actions_db.db"
engine = create_engine(DATABASE_URL, echo=False)
connection = engine.connect()

def get_stored_action():
    res = connection.execute(text("SELECT last_action FROM action_log WHERE log_key='menu_state'"))
    row = res.fetchone()
    return row[0] if row else "None"

def execute_and_save(action_name):
    connection.execute(
        text("UPDATE action_log SET last_action = :val WHERE log_key='menu_state'"),
        {"val": action_name}
    )
    connection.commit()
    lbl_status.config(text=f"Saved to DB: {action_name}")

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

init_action = get_stored_action()

mb = ttk.Menubutton(root, text="Database Menu", bootstyle=PRIMARY)
mb.pack(padx=20, pady=20)

menu = ttk.Menu(mb, tearoff=0)
menu.add_command(label="Sync Records", command=lambda: execute_and_save("Sync Records"))
menu.add_command(label="Export CSV", command=lambda: execute_and_save("Export CSV"))
mb["menu"] = menu

lbl_status = ttk.Label(root, text=f"Last Action from DB: {init_action}", bootstyle=SUCCESS, font=("Helvetica", 10))
lbl_status.pack(pady=10)

root.mainloop()
connection.close()

Part IV: Connecting to MySQL using SQLAlchemy

To connect your Menubutton action tracker to a centralized MySQL database server, update the SQLAlchemy connection string:

# SQLite Connection (Commented Out)
# DATABASE_URL = r"sqlite:///I:\My Drive\testing3\ttkbootstrap\actions_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
Menubutton dropdown list does not appear Failing to assign the Menu instance to the Menubutton via mb["menu"] = menu. Ensure you create a Menu widget with master as the Menubutton and assign it properly.
Tearoff line appears at top of dropdown menu Default Tkinter behavior allows menus to be torn off into separate floating windows. Disable tear-off by passing tearoff=0 during Menu initialization.

Frequently Asked Questions

Yes! Use menu.add_checkbutton(label="Option", variable=var) or menu.add_radiobutton(...).

Use index-based referencing: menu.entryconfig(index, state="disabled").



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