fix: use batched timer-based refresh instead of signals
- Replace signal/slot approach with QTimer-based batched updates - Add _refresh_pending flag and _request_refresh() method - Refresh timer runs at 10Hz (100ms) on main thread - Prevents race conditions and thread safety issues - All update methods now just set the pending flag
This commit is contained in:
parent
bd40d3d5e0
commit
4db34c2c2c
|
|
@ -295,7 +295,6 @@ class HUDOverlay(QWidget):
|
|||
|
||||
position_changed = pyqtSignal(QPoint)
|
||||
stats_updated = pyqtSignal(dict)
|
||||
refresh_needed = pyqtSignal() # Signal to trigger refresh on main thread
|
||||
|
||||
def __init__(self, parent=None, config_path: Optional[str] = None):
|
||||
super().__init__(parent)
|
||||
|
|
@ -324,8 +323,11 @@ class HUDOverlay(QWidget):
|
|||
self._timer = QTimer(self)
|
||||
self._timer.timeout.connect(self._update_session_time)
|
||||
|
||||
# Connect refresh signal to ensure GUI updates happen on main thread
|
||||
self.refresh_needed.connect(self._refresh_display, Qt.ConnectionType.QueuedConnection)
|
||||
# Batch refresh timer - prevents too frequent GUI updates
|
||||
self._refresh_pending = False
|
||||
self._refresh_timer = QTimer(self)
|
||||
self._refresh_timer.timeout.connect(self._do_refresh)
|
||||
self._refresh_timer.start(100) # Refresh at most 10 times per second
|
||||
|
||||
def _load_hud_config(self) -> HUDConfig:
|
||||
"""Load HUD configuration."""
|
||||
|
|
@ -784,6 +786,16 @@ class HUDOverlay(QWidget):
|
|||
# Widget was deleted
|
||||
pass
|
||||
|
||||
def _request_refresh(self):
|
||||
"""Request a refresh - will be batched and executed on main thread."""
|
||||
self._refresh_pending = True
|
||||
|
||||
def _do_refresh(self):
|
||||
"""Actually perform the refresh if pending."""
|
||||
if self._refresh_pending:
|
||||
self._refresh_pending = False
|
||||
self._refresh_display()
|
||||
|
||||
def _refresh_display(self):
|
||||
"""Refresh all display labels."""
|
||||
try:
|
||||
|
|
@ -869,7 +881,7 @@ class HUDOverlay(QWidget):
|
|||
|
||||
self._stats.recalculate()
|
||||
# Emit signal to refresh on main thread instead of calling directly
|
||||
self.refresh_needed.emit()
|
||||
self._request_refresh()
|
||||
logger.debug(f"[HUD] update_loot complete: shrapnel={self._stats.shrapnel_total}, other={self._stats.loot_other}")
|
||||
|
||||
def update_shrapnel(self, amount: Decimal):
|
||||
|
|
@ -883,7 +895,7 @@ class HUDOverlay(QWidget):
|
|||
self._stats.weapon_cost_total += cost_ped
|
||||
self._stats.cost_total += cost_ped
|
||||
self._stats.recalculate()
|
||||
self.refresh_needed.emit()
|
||||
self._request_refresh()
|
||||
|
||||
def update_armor_cost(self, cost_ped: Decimal):
|
||||
"""Update armor cost."""
|
||||
|
|
@ -892,7 +904,7 @@ class HUDOverlay(QWidget):
|
|||
self._stats.armor_cost_total += cost_ped
|
||||
self._stats.cost_total += cost_ped
|
||||
self._stats.recalculate()
|
||||
self.refresh_needed.emit()
|
||||
self._request_refresh()
|
||||
|
||||
def update_healing_cost(self, cost_ped: Decimal):
|
||||
"""Update healing cost."""
|
||||
|
|
@ -901,14 +913,14 @@ class HUDOverlay(QWidget):
|
|||
self._stats.healing_cost_total += cost_ped
|
||||
self._stats.cost_total += cost_ped
|
||||
self._stats.recalculate()
|
||||
self.refresh_needed.emit()
|
||||
self._request_refresh()
|
||||
|
||||
def update_kills(self, count: int = 1):
|
||||
"""Update kill count."""
|
||||
logger.debug(f"[HUD] update_kills called: count={count}, session_active={self.session_active}")
|
||||
if self.session_active:
|
||||
self._stats.kills += count
|
||||
self.refresh_needed.emit()
|
||||
self._request_refresh()
|
||||
|
||||
def update_skill(self, skill_name: str, amount: Decimal):
|
||||
"""Update skill gain tracking."""
|
||||
|
|
@ -920,13 +932,13 @@ class HUDOverlay(QWidget):
|
|||
self._stats.skill_gains[skill_name] += amount
|
||||
# Update total
|
||||
self._stats.total_skill_gained += amount
|
||||
self.refresh_needed.emit()
|
||||
self._request_refresh()
|
||||
|
||||
def update_globals(self):
|
||||
"""Update global count."""
|
||||
if self.session_active:
|
||||
self._stats.globals_count += 1
|
||||
self.refresh_needed.emit()
|
||||
self._request_refresh()
|
||||
|
||||
def update_damage(self, dealt: Decimal = Decimal('0'), taken: Decimal = Decimal('0')):
|
||||
"""Update damage stats."""
|
||||
|
|
@ -935,7 +947,7 @@ class HUDOverlay(QWidget):
|
|||
self._stats.damage_dealt += dealt
|
||||
if taken > 0:
|
||||
self._stats.damage_taken += taken
|
||||
self.refresh_needed.emit()
|
||||
self._request_refresh()
|
||||
|
||||
# === Event Handlers for LogWatcher ===
|
||||
|
||||
|
|
@ -943,20 +955,20 @@ class HUDOverlay(QWidget):
|
|||
"""Handle global event from LogWatcher."""
|
||||
if self.session_active:
|
||||
self._stats.globals_count += 1
|
||||
self.refresh_needed.emit()
|
||||
self._request_refresh()
|
||||
|
||||
def on_hof(self, value_ped=Decimal('0.0')):
|
||||
"""Handle Hall of Fame event from LogWatcher."""
|
||||
if self.session_active:
|
||||
self._stats.hofs_count += 1
|
||||
self.refresh_needed.emit()
|
||||
self._request_refresh()
|
||||
|
||||
def on_personal_global(self, value_ped=Decimal('0.0')):
|
||||
"""Handle personal global event from LogWatcher."""
|
||||
# Only count personal globals, not all globals
|
||||
if self.session_active:
|
||||
self._stats.globals_count += 1
|
||||
self.refresh_needed.emit()
|
||||
self._request_refresh()
|
||||
|
||||
def on_damage_dealt(self, damage):
|
||||
"""Handle damage dealt event from LogWatcher."""
|
||||
|
|
|
|||
Loading…
Reference in New Issue