This guide shows how to integrate the Bravura features into your real applications with minimal effort.
For full functionality, install these optional libraries:
# For enhanced NVIDIA GPU detection
pip install GPUtil
# For Windows WMI support (enhanced GPU detection)
pip install pywin32
# For system information
pip install psutil
Note: The toolkit works without these libraries but provides enhanced functionality when they're installed.
---
from bravura import get_audio_analyzer_framework
# Get framework class and create instance
AppClass = get_audio_analyzer_framework()
app = AppClass()
class YourApplication(AnalysisGUIFramework):
def your_real_processing_function(self):
# Start timer when beginning work
self._start_timer()
total_items = 100
for i, item in enumerate(your_data):
# Your real processing here
result = process_item(item)
# Update progress with ETA calculation
progress = (i + 1) / total_items * 100
self._update_progress_with_eta(progress, f"Processing {item.name}...")
# Timer automatically shows completion time
def your_batch_processing(self, files):
"""Example: Process multiple files with timer and ETA."""
self._start_timer()
total_files = len(files)
for i, file_path in enumerate(files):
# Real file processing
try:
result = your_file_processor(file_path)
# Update with meaningful progress
progress = ((i + 1) / total_files) * 100
filename = os.path.basename(file_path)
self._update_progress_with_eta(progress, f"Processed {filename}")
except Exception as e:
self._log_message(f"❌ Error processing {file_path}: {e}")
# Timer automatically resets after completion display
---
The toolkit automatically detects GPUs when initialized. No code changes needed!
class YourApplication(AnalysisGUIFramework):
def check_gpu_capability(self):
"""Check if GPU acceleration is available for your app."""
if self.use_gpu_var.get() and self.detected_gpus:
primary_gpu = self.primary_gpu
# Check GPU memory for your requirements
if 'memory_total' in primary_gpu:
gpu_memory_mb = primary_gpu['memory_total']
if gpu_memory_mb >= 4000: # 4GB minimum
return True
else:
self._log_message(f"⚠️ GPU has {gpu_memory_mb}MB, need 4GB minimum")
return True # GPU available
return False # Use CPU processing
def your_gpu_accelerated_function(self):
"""Example GPU-accelerated processing."""
if self.check_gpu_capability():
# Use GPU processing
self._log_message(f"🔥 Using GPU: {self.primary_gpu['name']}")
return self.gpu_process_data()
else:
# Fallback to CPU
self._log_message("⚡ Using CPU processing")
return self.cpu_process_data()
def debug_gpu_issues(self):
"""Get detailed GPU info for troubleshooting."""
# This runs the same diagnostics as the button
diagnostics = self._get_comprehensive_gpu_diagnostics()
# Access specific information
if diagnostics['detected_gpus']:
for gpu in diagnostics['detected_gpus']:
print(f"GPU: {gpu['name']}")
print(f"Memory: {gpu.get('memory_total', 'Unknown')} MB")
print(f"Driver: {gpu.get('driver', 'Unknown')}")
return diagnostics
---
class AudioProcessor(AnalysisGUIFramework):
def process_audio_files(self, file_paths):
self._start_timer()
for i, file_path in enumerate(file_paths):
# Real audio processing
audio_data = load_audio(file_path)
if self.check_gpu_capability():
# GPU-accelerated spectral analysis
features = gpu_extract_features(audio_data)
else:
# CPU fallback
features = cpu_extract_features(audio_data)
# Update progress
progress = ((i + 1) / len(file_paths)) * 100
filename = os.path.basename(file_path)
self._update_progress_with_eta(progress, f"Analyzing {filename}")
class ImageProcessor(AnalysisGUIFramework):
def batch_image_processing(self, images):
self._start_timer()
# Check GPU memory requirements
if self.use_gpu_var.get() and self.primary_gpu:
gpu_memory = self.primary_gpu.get('memory_total', 0)
if gpu_memory < 2000: # Need 2GB for image processing
self._log_message("⚠️ Insufficient GPU memory, using CPU")
self.use_gpu_var.set(False)
for i, image_path in enumerate(images):
# Real image processing
if self.use_gpu_var.get():
result = gpu_process_image(image_path)
else:
result = cpu_process_image(image_path)
# Update with ETA
progress = ((i + 1) / len(images)) * 100
self._update_progress_with_eta(progress, f"Processing image {i+1}")
---
def check_custom_gpu_requirements(self):
"""Check if GPU meets your specific requirements."""
if not self.detected_gpus:
return False
gpu = self.primary_gpu
# Check NVIDIA GPU for CUDA
if gpu.get('type') == 'NVIDIA':
# Check for specific compute capability, memory, etc.
memory_gb = gpu.get('memory_total', 0) / 1024
if memory_gb >= 8: # Need 8GB for your application
return True
return False
def update_custom_progress(self, current, total, operation):
"""Custom progress updates with your terminology."""
progress = (current / total) * 100
message = f"{operation}: {current}/{total} items"
self._update_progress_with_eta(progress, message)
---
# Good: Always have CPU fallback
if self.use_gpu_var.get() and self.check_gpu_capability():
result = gpu_process()
else:
result = cpu_process()
# Bad: Assuming GPU is always available
result = gpu_process() # Will fail if no GPU
# Good: Descriptive messages
self._update_progress_with_eta(45, "Extracting features from audio segment 3/7")
# Bad: Generic messages
self._update_progress_with_eta(45, "Processing...")
def check_memory_requirements(self, data_size_mb):
"""Check if GPU has enough memory for processing."""
if self.primary_gpu and 'memory_free' in self.primary_gpu:
free_memory = self.primary_gpu['memory_free']
return free_memory > (data_size_mb * 1.2) # 20% safety margin
return False
---
demo_timer_eta.py for timer system examples_demo_run_gpu_diagnostics() for GPU detection examplestheme_manager.py for theming integrationglowing_progress_bar.py for progress bar customization---
pip install GPUtil pywin32_start_timer() before starting work_update_progress_with_eta() instead of manual updates_reset_timer() manually (auto-resets)---
Step 1: Apply Bravura Theme
from bravura.themes import apply_theme
# Apply theme to style all widgets
apply_theme(root, "wigley_site")
Step 2: Enhance Hero Actions
from bravura.components import PremiumButton
# Primary save action
save_btn = PremiumButton(
header_frame,
text="💾 Save Project",
command=self.save_project,
style="primary",
loading=False # Set to True during save operation
)
save_btn.pack(side=tk.RIGHT, padx=10)
Step 3: Use Compact Buttons for Dense UIs
from bravura.components import CompactPremiumButton
# Toolbar button
refresh_btn = CompactPremiumButton(
toolbar,
text="Refresh",
width=12, # Character-based width
style="primary"
)
Step 4: Or Use Factory for Automatic Selection
from bravura.components import ButtonFactory
# Automatically picks right component
hero_btn = ButtonFactory.create(
parent,
text="Save",
context="hero" # Creates PremiumButton
)
toolbar_btn = ButtonFactory.create(
parent,
text="Bold",
context="toolbar", # Creates CompactPremiumButton
width=8
)
When: Enhancing existing application with Bravura buttons
Steps:
Example:
class ExistingApp:
def integrate_bravura(self):
# Step 1: Apply theme
apply_theme(self.root, "wigley_site")
# Step 2: Enhance hero action
# Before: ttk.Button(self.header, text="Save")
# After:
self.save_btn = PremiumButton(
self.header,
text="💾 Save Project",
command=self.save,
style="primary"
)
# Step 3: Keep toolbar buttons as ttk.Button
# They're automatically styled by the theme
for action in ["Bold", "Italic", "Underline"]:
btn = ttk.Button(
self.toolbar,
text=action,
width=8
)
btn.pack(side=tk.LEFT, padx=2)
Result: Clear visual hierarchy with minimal code changes
When: Building new application or major UI overhaul
Steps:
Example:
class NewApp:
def create_ui(self):
# Hero action
self.save_btn = ButtonFactory.create_hero(
self.header,
text="💾 Save Project",
command=self.save
)
# Toolbar actions
for action in ["Bold", "Italic", "Underline"]:
btn = ButtonFactory.create_toolbar(
self.toolbar,
text=action,
command=lambda a=action: self.format(a),
width=8
)
btn.pack(side=tk.LEFT, padx=2)
# Form buttons
ok_btn = ButtonFactory.create_form(
self.form,
text="OK",
command=self.on_ok,
width=10,
style="success"
)
cancel_btn = ButtonFactory.create_form(
self.form,
text="Cancel",
command=self.on_cancel,
width=10,
style="secondary"
)
Result: Consistent, professional appearance throughout application
Use PremiumButton when:
Use CompactPremiumButton when:
Use themed ttk.Button when:
Use ButtonFactory when:
class ToolbarApp:
def create_ui(self):
# Header with hero action
self.header = tk.Frame(self.root)
self.save_btn = ButtonFactory.create_hero(
self.header,
text="💾 Save",
command=self.save
)
# Toolbar with compact actions
self.toolbar = tk.Frame(self.root)
actions = ["Bold", "Italic", "Underline", "Color", "Size"]
for action in actions:
ButtonFactory.create_toolbar(
self.toolbar,
text=action,
width=8
).pack(side=tk.LEFT, padx=2)
class FormDialog:
def create_buttons(self):
button_frame = tk.Frame(self.dialog)
# Use CompactPremiumButton for uniform sizing
ok_btn = CompactPremiumButton(
button_frame,
text="OK",
command=self.on_ok,
width=10,
style="success"
)
ok_btn.pack(side=tk.LEFT, padx=5)
cancel_btn = CompactPremiumButton(
button_frame,
text="Cancel",
command=self.on_cancel,
width=10,
style="secondary"
)
cancel_btn.pack(side=tk.LEFT, padx=5)
class DataManager:
def create_ui(self):
# Primary action
process_btn = PremiumButton(
self.main_frame,
text="🚀 Process Data",
command=self.process_data,
style="primary"
)
# Table actions
actions_frame = tk.Frame(self.root)
for action in ["Add", "Edit", "Delete", "Export"]:
CompactPremiumButton(
actions_frame,
text=action,
width=8
).pack(side=tk.LEFT, padx=2)
def process_data(self):
# Show loading during operation
self.process_btn.set_loading(True)
# ... process data ...
self.process_btn.set_loading(False)
PremiumButton supports loading states for long-running operations:
def save_project(self):
# Show loading
self.save_btn.set_loading(True)
try:
# Perform save operation
result = self.perform_save()
if result.success:
self.log_success("✅ Project saved successfully")
else:
self.log_error(f"❌ Save failed: {result.error}")
finally:
# Hide loading
self.save_btn.set_loading(False)
When integrating Bravura buttons into existing application:
❌ DON'T: Replace every button with PremiumButton
# This creates visual chaos
for button_text in all_buttons:
PremiumButton(parent, text=button_text) # Too many hero buttons!
✅ DO: Use appropriate component for each context
# Clear hierarchy
hero = PremiumButton(header, text="Save") # 1-3 per page
toolbar = CompactPremiumButton(toolbar, text="Bold", width=8) # Many per page
form = ttk.Button(form, text="Cancel") # Themed automatically
❌ DON'T: Fight button sizes with overrides
# Trying to make PremiumButton small
btn = PremiumButton(
toolbar,
text="Bold",
padx=1,
pady=0,
font=("Arial", 8) # Still looks wrong!
)
✅ DO: Use the right component
# Designed for this use case
btn = CompactPremiumButton(
toolbar,
text="Bold",
width=8 # Perfect fit!
)
/Bravura/docs/BUTTON_USAGE_GUIDE.md/Bravura/docs/API_REFERENCE.md (Button Components section)/Bravura Demos and Templates/demos/enterprise/demos/button_migration_demo.py---
Ready to integrate? Start with copying the examples above into your application!