5.2 KiB
UI Flickering Fix Summary
Problem Description
The UI elements were flickering when the user scrolled through the table, causing a poor user experience and making the application feel unresponsive.
Root Causes Identified
-
Auto-save triggering full UI refresh: The
_auto_save_callbackmethod was callingrefresh_data_display()every 5 minutes, which completely refreshed the UI even during user interaction. -
Real-time filter updates: The search filter widget was triggering
update_callback()on every keystroke, causing immediate and frequent full data refreshes. -
Inefficient tree updates: The
refresh_data_displaymethod was loading data multiple times and completely replacing all tree items, causing visible flickering. -
Lack of scroll position preservation: When the tree was refreshed, the user's scroll position was lost, causing jarring jumps.
Solutions Implemented
1. Auto-save Optimization (thechart main application)
def _auto_save_callback(self) -> None:
"""Callback function for auto-save operations."""
try:
# Only save data, don't refresh the display during auto-save
# This prevents flickering during user interaction
logger.debug("Auto-save callback executed successfully")
except Exception as e:
logger.error(f"Auto-save callback failed: {e}")
Impact: Eliminates UI interruptions during auto-save operations.
2. Debounced Filter Updates (thechart.ui.search_filter_ui)
- Added 300ms debouncing mechanism to prevent excessive filter updates
- Consolidated filter updates into a single batch operation
- Replaced immediate callbacks with debounced updates
def _debounced_update(self) -> None:
"""Update filters with debouncing to prevent excessive calls."""
# Cancel any pending update and schedule a new one
if self._update_timer:
with contextlib.suppress(tk.TclError):
self.parent.after_cancel(self._update_timer)
self._update_timer = self.parent.after(
self._debounce_delay, self._execute_filter_update
)
Impact: Reduces filter update frequency from every keystroke to maximum once per 300ms.
3. Efficient Tree Updates (application update path)
- Separated tree update logic into
_update_tree_efficiently()method - Added scroll position preservation
- Eliminated redundant data loading
- Used
update_idletasks()for smoother UI updates
def _update_tree_efficiently(self, df: pd.DataFrame) -> None:
"""Update tree view efficiently to reduce flickering."""
# Store and restore scroll position
current_scroll_top = 0
with contextlib.suppress(tk.TclError, IndexError):
current_scroll_top = self.tree.yview()[0]
# Batch operations and restore position
# ... update logic ...
self.root.update_idletasks()
with contextlib.suppress(tk.TclError, IndexError):
if current_scroll_top > 0:
self.tree.yview_moveto(current_scroll_top)
Impact: Maintains scroll position and reduces visual disruption during updates.
4. Optimized Data Loading (application update path)
- Eliminated redundant
load_data()calls - Used single data copy for both filtered and unfiltered operations
- Improved memory efficiency
def refresh_data_display(self, apply_filters: bool = False) -> None:
# Load data once and make a copy for graph updates
df: pd.DataFrame = self.data_manager.load_data()
original_df = df.copy() # Keep a copy for graph updates
# Apply filters only if needed
if apply_filters and self.data_filter.get_filter_summary()["has_filters"]:
df = self.data_filter.apply_filters(df)
Impact: Reduces I/O operations and memory usage.
5. Scroll Optimization (thechart.ui.ui_manager)
- Added optimized scroll command with threshold-based updates
- Reduced scrollbar update frequency for better performance
def _optimize_tree_scrolling(self, tree: ttk.Treeview) -> None:
"""Optimize tree scrolling to reduce flickering and improve performance."""
last_scroll_position = [0.0, 1.0]
def optimized_yscrollcommand(first, last):
# Only update if position significantly changed
first_f, last_f = float(first), float(last)
if (abs(first_f - last_scroll_position[0]) > 0.001 or
abs(last_f - last_scroll_position[1]) > 0.001):
# Update scrollbar efficiently
Impact: Reduces scroll update frequency and improves scrolling smoothness.
Testing Results
The application now runs without the previous UI flickering issues:
- ✅ Smooth scrolling through table data
- ✅ No interruptions from auto-save operations
- ✅ Responsive search/filter updates with debouncing
- ✅ Preserved scroll position during data updates
- ✅ Reduced CPU usage during scroll operations
Files Modified
- Main application - Auto-save optimization and efficient tree updates
thechart.ui.search_filter_ui- Debounced filter updatesthechart.ui.ui_manager- Optimized scroll handling
Verification
Run the test script to verify improvements:
python test_ui_flickering_fix.py
The application should now provide a smooth, flicker-free user experience when scrolling through data entries.