This guide covers the most common mistakes developers make when using the Bravura SDK and shows the correct patterns.
---
---
WRONG:
# This is the most common mistake!
style = ttk.Style()
style.configure("TFrame", background="#0F141B")
style.configure("TLabel", foreground="#E8EEF4")
style.configure("TEntry", fieldbackground="#131A22")
# ... 50 more lines of manual styling ...
Why it's wrong:
✅ CORRECT:
from bravura.themes.theme_manager import ProfessionalThemeManager
# Initialize theme manager
self.theme_manager = ProfessionalThemeManager(self)
# Apply theme - ONE LINE!
self.theme_manager.apply_theme("wigley_site")
# That's it! All widgets are now professionally styled.
What this does:
ttk widgets automatically---
WRONG:
def __init__(self):
self.root = tk.Tk()
self.create_ui() # Widgets created FIRST
# Theme applied AFTER widgets exist
self.theme_manager = ProfessionalThemeManager(self)
self.theme_manager.apply_theme("wigley_site") # Too late!
Why it's wrong:
✅ CORRECT:
def __init__(self):
self.root = tk.Tk()
# Apply theme BEFORE creating widgets
self.theme_manager = ProfessionalThemeManager(self)
self.theme_manager.apply_theme("wigley_site")
# NOW create widgets - they'll get the theme automatically
self.create_ui()
---
WRONG:
# Hardcoded colors break when themes change
frame = ttk.Frame(self.root)
frame.configure(background="#0F141B") # Hardcoded!
label = ttk.Label(frame, text="Hello")
label.configure(foreground="#E8EEF4") # Hardcoded!
✅ CORRECT:
# Let ThemeManager handle colors
frame = ttk.Frame(self.root)
# No manual color configuration needed!
label = ttk.Label(frame, text="Hello")
# ThemeManager sets the correct colors automatically
If you MUST set colors, use theme tokens:
from bravura.themes.theme_tokens import WIGLEY_SITE_TOKENS
# Use theme tokens instead of hardcoded values
bg_color = WIGLEY_SITE_TOKENS["surface_1"]
text_color = WIGLEY_SITE_TOKENS["text_primary"]
---
WRONG:
# Button sizes based on text only - inconsistent widths
save_btn = PremiumButton(parent, text="Save", command=self.save)
connect_btn = PremiumButton(parent, text="Connect to Database", command=self.connect)
# Result: Buttons have wildly different widths
✅ CORRECT:
# Specify consistent widths for professional appearance
save_btn = PremiumButton(
parent,
text="Save",
command=self.save,
width=18 # Consistent width
)
connect_btn = PremiumButton(
parent,
text="Connect to Database",
command=self.connect,
width=18 # Same width - looks professional
)
Recommended widths:
PremiumButton): width=18CompactPremiumButton): width=12width=10width=25 (max)---
WRONG:
# Using PremiumButton for everything
toolbar_btn = PremiumButton(toolbar, text="Refresh", ...) # Too big!
menu_btn = PremiumButton(menu, text="Settings", ...) # Too big!
✅ CORRECT:
from bravura.components import PremiumButton, CompactPremiumButton
# Use PremiumButton for PRIMARY actions
save_btn = PremiumButton(header, text="Save Document", width=18)
# Use CompactPremiumButton for TOOLBARS and UTILITIES
toolbar_btn = CompactPremiumButton(toolbar, text="Refresh", width=12)
menu_btn = CompactPremiumButton(menu, text="Settings", width=12)
Or use ButtonFactory for automatic selection:
from bravura.components import ButtonFactory
# Automatically selects the right button type
hero_btn = ButtonFactory.create(header, text="Save", context="hero") # → PremiumButton
toolbar_btn = ButtonFactory.create(toolbar, text="Refresh", context="toolbar") # → CompactPremiumButton
---
WRONG:
# Wrong import paths
from bravura import PremiumButton # ❌ Wrong!
from bravura import ThemeManager # ❌ Wrong!
from bravura.themes import ProfessionalThemeManager # ❌ Wrong!
✅ CORRECT:
# Correct import paths
from bravura.components import PremiumButton
from bravura.components import CompactPremiumButton
from bravura.components import AmbientBackground
from bravura.themes.theme_manager import ProfessionalThemeManager
Convenience import (everything in one place):
# Import multiple components at once
from bravura.components import (
PremiumButton,
CompactPremiumButton,
AmbientBackground,
ButtonFactory,
ToolTip
)
---
WRONG:
# Trying to import without SDK in path
from bravura.components import PremiumButton # ModuleNotFoundError!
✅ CORRECT (Installed via pip):
# If installed via pip, imports work automatically
from bravura.components import PremiumButton
✅ CORRECT (Development/Source):
import sys
from pathlib import Path
# Add Bravura to path
bravura_path = Path(__file__).parent / "Bravura" / "src"
if bravura_path.exists():
sys.path.insert(0, str(bravura_path))
# Now imports work
from bravura.components import PremiumButton
---
WRONG:
# Mixing tk and ttk widgets - inconsistent styling
frame = tk.Frame(self.root) # tk widget - won't get theme!
label = ttk.Label(frame, text="Hello") # ttk widget - gets theme
Problem: tk.Frame doesn't support ttk.Style, so it won't match the theme.
✅ CORRECT:
# Use ttk widgets exclusively for consistent theming
frame = ttk.Frame(self.root) # ttk widget - gets theme!
label = ttk.Label(frame, text="Hello") # ttk widget - gets theme!
Exception: Use tk widgets only when you need features not available in ttk:
# tk.Text is fine - ttk doesn't have a Text widget
text_widget = tk.Text(parent, bg="#131A22", fg="#E8EEF4")
---
WRONG:
# tk.Text doesn't get automatic theming
text_widget = tk.Text(parent) # White background, black text - doesn't match theme!
✅ CORRECT:
# Manually configure tk.Text to match theme
text_widget = tk.Text(
parent,
bg="#131A22", # Dark background
fg="#E8EEF4", # Light text
insertbackground="#E8EEF4", # Light cursor
selectbackground="#20C6B7", # Teal selection
selectforeground="#FFFFFF", # White selected text
font=("Consolas", 10)
)
Or use theme tokens:
from bravura.themes.theme_tokens import WIGLEY_SITE_TOKENS
text_widget = tk.Text(
parent,
bg=WIGLEY_SITE_TOKENS["surface_2"],
fg=WIGLEY_SITE_TOKENS["text_primary"],
insertbackground=WIGLEY_SITE_TOKENS["text_primary"],
selectbackground=WIGLEY_SITE_TOKENS["teal"],
selectforeground="#FFFFFF"
)
---
WRONG:
def create_ui(self):
# Create widgets first
self.frame = ttk.Frame(self.root)
self.frame.pack(fill="both", expand=True)
# Create background AFTER - won't be visible!
self.ambient_bg = AmbientBackground(self.root, ...)
Why it's wrong:
✅ CORRECT:
def __init__(self):
self.root = tk.Tk()
# Apply theme
self.theme_manager = ProfessionalThemeManager(self)
self.theme_manager.apply_theme("wigley_site")
# Create background FIRST (before widgets)
self.ambient_bg = AmbientBackground(
self.root,
enable_animation=True,
glow_effects=True
)
# Set root background to match
self.root.configure(bg="#0B1115")
# NOW create widgets - they'll appear on top of background
self.create_ui()
---
WRONG:
# Opaque frames completely block ambient background
frame = ttk.Frame(self.root, style="TFrame") # Completely opaque!
Problem: ttk frames are opaque by default, hiding the ambient background.
✅ SOLUTION:
The theme already handles frame transparency! Just use standard ttk.Frame:
# Theme manager configures frames with proper backgrounds
frame = ttk.Frame(self.root)
# Background shows through at window edges and between widgets
If you need more transparency, use a tk.Canvas:
# For truly transparent areas
canvas = tk.Canvas(
self.root,
bg="#0B1115",
highlightthickness=0
)
canvas.pack(fill="both", expand=True)
---
WRONG:
# Missing theme_tokens = particles won't adapt to themes
ambient_bg = AmbientBackground(
self.root,
enable_animation=True,
particle_count=20
# Missing theme_tokens parameter!
)
Problem: Without theme_tokens, particles use hardcoded colors that don't match your theme.
✅ CORRECT:
# Pass theme colors for theme-aware particles
ambient_bg = AmbientBackground(
self.root,
width=800,
height=600,
theme_tokens=self.theme_manager.get_current_theme_colors(), # Essential!
enable_animation=True,
particle_count=20,
glow_effects=True
)
When theme changes, update theme tokens instantly:
def change_theme(self, new_theme):
# Apply new theme
self.theme_manager.apply_theme(new_theme)
# Update ambient background colors instantly (NEW in v1.0.0)
if hasattr(self, 'ambient_bg') and self.ambient_bg:
self.ambient_bg.set_theme_tokens(
self.theme_manager.get_current_theme_colors() # New colors!
)
# 10x faster than recreation, no visual flicker!
---
WRONG:
# Too many particles = unnecessary
ambient_bg = AmbientBackground(
self.root,
theme_tokens=theme_colors,
enable_animation=True,
particle_count=100, # Excessive (60 is max)
animation_speed="fast"
)
✅ CORRECT:
# Optimal particle count with buttery-smooth 60 FPS performance
ambient_bg = AmbientBackground(
self.root,
theme_tokens=self.theme_manager.get_current_theme_colors(),
enable_animation=True,
particle_count=30, # Sweet spot for visual richness
animation_speed="medium", # Fixed 60 FPS animation
glow_effects=True
)
# Runs at smooth 60 FPS with <2% CPU usage even at 30-40 particles!
Recommended particle counts (all run smoothly at 60 FPS):
particle_count=10 (ultra-minimal CPU usage)particle_count=20 (default, <1% CPU)particle_count=30-40 (rich visuals, <2% CPU)Performance Note: Thanks to optimized 60 FPS rendering with harmonic easing, even 40 particles maintain buttery-smooth animation with minimal CPU impact. The animation speed parameter only affects drift velocity, not smoothness - it's always 60 FPS!
---
WRONG:
# Always animating - can cause motion sickness
ambient_bg = AmbientBackground(
self.root,
enable_animation=True # Always on
)
✅ CORRECT:
# Respect user preferences for reduced motion
import platform
# Check system preferences (simplified)
reduced_motion = False # Get from system settings
ambient_bg = AmbientBackground(
self.root,
enable_animation=not reduced_motion, # Disable if user prefers
animation_speed="slow" if not reduced_motion else None,
glow_effects=True
)
---
WRONG:
from bravura.components import GlowingProgressBar, GlowingProgressManager
manager = GlowingProgressManager(root)
bar = GlowingProgressBar(
parent=container,
manager=manager,
bar_type="rainbow",
width=500
)
bar.pack()
# This silently fails! Canvas not initialized yet
bar.start_glow_animation() # ❌ Too early!
bar.set_progress(50)
Why it's wrong:
GlowingProgressBar initializes canvas elements asynchronously via after(1, ...)start_glow_animation() is called immediately, self.progress_rect is still None✅ CORRECT:
from bravura.components import GlowingProgressBar, GlowingProgressManager
manager = GlowingProgressManager(root)
bar = GlowingProgressBar(
parent=container,
manager=manager,
bar_type="rainbow",
width=500
)
bar.pack()
# Wait for canvas initialization before starting animation
def start_animation():
bar.start_glow_animation()
bar.set_progress(50)
root.after(100, start_animation) # ✅ Delay allows canvas to initialize
Alternative Pattern (for immediate display):
# Create bar and pack it
bar = GlowingProgressBar(parent, manager, bar_type="rainbow", width=500)
bar.pack()
# Set initial state immediately (will show once canvas initializes)
bar.set_progress(50)
bar.set_label_text("Processing...")
# Start animation with delay
root.after(100, bar.start_glow_animation) # ✅ Clean one-liner
When to use this pattern:
GlowingProgressBar with animationsstart_glow_animation() immediately after creationWhen you DON'T need the delay:
set_progress() only - no animation neededTechnical Details:
The GlowingProgressBar creates canvas elements asynchronously:
# In glowing_progress_bar.py source
def _create_widgets(self):
# ...canvas creation...
# Initialize canvas elements AFTER a delay
self.parent.after(1, self._initialize_canvas_elements)
This design allows the widget to be fully rendered before drawing, but requires animations to wait for initialization.
---
| Do | Why |
|---|---|
| Use `ProfessionalThemeManager` | Handles ALL theming automatically |
| Apply theme BEFORE creating widgets | Ensures consistent styling |
| Specify button widths | Professional, consistent appearance |
| Use `CompactPremiumButton` for toolbars | Space-efficient, appropriate sizing |
| Create `AmbientBackground` FIRST | Must render behind widgets |
| Use `ttk` widgets | Get automatic theming |
| Use theme tokens for colors | Maintains consistency when themes change |
| Don't | Why |
|---|---|
| Manually configure `ttk.Style` | ThemeManager handles this |
| Hardcode colors | Breaks theme switching |
| Mix `tk` and `ttk` randomly | Inconsistent styling |
| Use `PremiumButton` everywhere | Wrong button for toolbars |
| Create background after widgets | Won't be visible |
| Use 100+ particles | Performance issues |
| Ignore accessibility | Motion sickness, contrast issues |
---
Before releasing your Bravura application, verify:
ProfessionalThemeManager for theming (not manual ttk.Style)PremiumButton with width specificationCompactPremiumButton for toolbars (width=12)AmbientBackground created FIRST (if using)ttk widgets (not tk) for automatic themingtk.Text configuration matches theme---
If you're still having issues:
QUICK_START.mdLocal Server Management Tools/hostinger_database_manager_bravura_poc.py---
Remember: The Bravura SDK is designed to make your life EASIER. If you find yourself writing lots of manual styling code, you're probably doing it wrong! Let ThemeManager and the premium components do the work for you.
Happy coding! 🚀