fix: use signal/slot for thread-safe GUI updates
- Add refresh_needed signal to HUDOverlay - Connect signal to _refresh_display with QueuedConnection - Update all update methods to emit signal instead of calling _refresh_display directly - This ensures all GUI operations (setStyleSheet, setText) happen on main thread - Fixes crash caused by GUI operations from LogWatcher thread
This commit is contained in:
parent
0a6e4358de
commit
63f215a3a1
|
|
@ -295,6 +295,7 @@ 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)
|
||||
|
|
@ -323,6 +324,9 @@ 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)
|
||||
|
||||
def _load_hud_config(self) -> HUDConfig:
|
||||
"""Load HUD configuration."""
|
||||
try:
|
||||
|
|
@ -883,7 +887,8 @@ class HUDOverlay(QWidget):
|
|||
self._stats.loot_other += value_ped
|
||||
|
||||
self._stats.recalculate()
|
||||
self._refresh_display()
|
||||
# Emit signal to refresh on main thread instead of calling directly
|
||||
self.refresh_needed.emit()
|
||||
logger.debug(f"[HUD] update_loot complete: shrapnel={self._stats.shrapnel_total}, other={self._stats.loot_other}")
|
||||
|
||||
def update_shrapnel(self, amount: Decimal):
|
||||
|
|
@ -897,7 +902,7 @@ class HUDOverlay(QWidget):
|
|||
self._stats.weapon_cost_total += cost_ped
|
||||
self._stats.cost_total += cost_ped
|
||||
self._stats.recalculate()
|
||||
self._refresh_display()
|
||||
self.refresh_needed.emit()
|
||||
|
||||
def update_armor_cost(self, cost_ped: Decimal):
|
||||
"""Update armor cost."""
|
||||
|
|
@ -906,7 +911,7 @@ class HUDOverlay(QWidget):
|
|||
self._stats.armor_cost_total += cost_ped
|
||||
self._stats.cost_total += cost_ped
|
||||
self._stats.recalculate()
|
||||
self._refresh_display()
|
||||
self.refresh_needed.emit()
|
||||
|
||||
def update_healing_cost(self, cost_ped: Decimal):
|
||||
"""Update healing cost."""
|
||||
|
|
@ -915,14 +920,14 @@ class HUDOverlay(QWidget):
|
|||
self._stats.healing_cost_total += cost_ped
|
||||
self._stats.cost_total += cost_ped
|
||||
self._stats.recalculate()
|
||||
self._refresh_display()
|
||||
self.refresh_needed.emit()
|
||||
|
||||
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_display()
|
||||
self.refresh_needed.emit()
|
||||
|
||||
def update_skill(self, skill_name: str, amount: Decimal):
|
||||
"""Update skill gain tracking."""
|
||||
|
|
@ -934,13 +939,13 @@ class HUDOverlay(QWidget):
|
|||
self._stats.skill_gains[skill_name] += amount
|
||||
# Update total
|
||||
self._stats.total_skill_gained += amount
|
||||
self._refresh_display()
|
||||
self.refresh_needed.emit()
|
||||
|
||||
def update_globals(self):
|
||||
"""Update global count."""
|
||||
if self.session_active:
|
||||
self._stats.globals_count += 1
|
||||
self._refresh_display()
|
||||
self.refresh_needed.emit()
|
||||
|
||||
def update_damage(self, dealt: Decimal = Decimal('0'), taken: Decimal = Decimal('0')):
|
||||
"""Update damage stats."""
|
||||
|
|
@ -949,7 +954,7 @@ class HUDOverlay(QWidget):
|
|||
self._stats.damage_dealt += dealt
|
||||
if taken > 0:
|
||||
self._stats.damage_taken += taken
|
||||
self._refresh_display()
|
||||
self.refresh_needed.emit()
|
||||
|
||||
# === Event Handlers for LogWatcher ===
|
||||
|
||||
|
|
@ -957,20 +962,20 @@ class HUDOverlay(QWidget):
|
|||
"""Handle global event from LogWatcher."""
|
||||
if self.session_active:
|
||||
self._stats.globals_count += 1
|
||||
self._refresh_display()
|
||||
self.refresh_needed.emit()
|
||||
|
||||
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_display()
|
||||
self.refresh_needed.emit()
|
||||
|
||||
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_display()
|
||||
self.refresh_needed.emit()
|
||||
|
||||
def on_damage_dealt(self, damage):
|
||||
"""Handle damage dealt event from LogWatcher."""
|
||||
|
|
|
|||
Loading…
Reference in New Issue