Fix mode panels: Screen → Container with on_show/on_hide lifecycle
Textual's ContentSwitcher expects regular Widget/Container children, not Screen subclasses. Screen's on_mount fires for all children at once regardless of visibility, so demo workers for all 5 modes started simultaneously and competed for the bridge. Container children get proper on_show/on_hide from ContentSwitcher's visibility toggling — only the active panel's worker runs.
This commit is contained in:
parent
64c33985a3
commit
8da486719a
@ -10,8 +10,7 @@ import os
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "..", "tools"))
|
||||
|
||||
from textual.app import ComposeResult
|
||||
from textual.containers import Horizontal, Vertical
|
||||
from textual.screen import Screen
|
||||
from textual.containers import Container, Horizontal, Vertical
|
||||
from textual.widgets import Label, Input, Button, Static, ProgressBar, Checkbox
|
||||
from textual import work
|
||||
from textual.worker import Worker
|
||||
@ -37,7 +36,7 @@ def _alloc_table(start: float, stop: float) -> str:
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
class LBandScreen(Screen):
|
||||
class LBandScreen(Container):
|
||||
"""L-band direct input analyzer with allocation annotations."""
|
||||
|
||||
DEFAULT_CSS = """
|
||||
@ -130,11 +129,11 @@ class LBandScreen(Screen):
|
||||
yield Button("Sweep", id="lband-sweep-btn", variant="success")
|
||||
yield Button("Stop", id="lband-stop-btn", variant="error")
|
||||
|
||||
def on_mount(self) -> None:
|
||||
if self._bridge.is_demo:
|
||||
def on_show(self) -> None:
|
||||
if self._bridge.is_demo and not self._sweeping:
|
||||
self._start_sweep()
|
||||
|
||||
def on_unmount(self) -> None:
|
||||
def on_hide(self) -> None:
|
||||
self._stop_sweep()
|
||||
|
||||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||||
|
||||
@ -6,8 +6,7 @@ sparkline history.
|
||||
"""
|
||||
|
||||
from textual.app import ComposeResult
|
||||
from textual.containers import Horizontal, Vertical
|
||||
from textual.screen import Screen
|
||||
from textual.containers import Container, Horizontal, Vertical
|
||||
from textual.widgets import Label, Input, Button, Static
|
||||
from textual import work
|
||||
from textual.worker import Worker, WorkerState
|
||||
@ -16,7 +15,7 @@ from skywalker_tui.widgets.signal_gauge import SignalGauge
|
||||
from skywalker_tui.widgets.sparkline_widget import SparklineWidget
|
||||
|
||||
|
||||
class MonitorScreen(Screen):
|
||||
class MonitorScreen(Container):
|
||||
"""Real-time signal monitor with gauge and sparkline."""
|
||||
|
||||
DEFAULT_CSS = """
|
||||
@ -96,12 +95,12 @@ class MonitorScreen(Screen):
|
||||
yield Button("Start", id="mon-start", variant="success")
|
||||
yield Button("Stop", id="mon-stop", variant="error")
|
||||
|
||||
def on_mount(self) -> None:
|
||||
def on_show(self) -> None:
|
||||
# Auto-start polling in demo mode
|
||||
if self._bridge.is_demo:
|
||||
if self._bridge.is_demo and not self._polling:
|
||||
self._start_polling()
|
||||
|
||||
def on_unmount(self) -> None:
|
||||
def on_hide(self) -> None:
|
||||
self._stop_polling()
|
||||
|
||||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||||
|
||||
@ -8,8 +8,7 @@ import struct
|
||||
import time
|
||||
|
||||
from textual.app import ComposeResult
|
||||
from textual.containers import Horizontal, Vertical
|
||||
from textual.screen import Screen
|
||||
from textual.containers import Container, Horizontal, Vertical
|
||||
from textual.widgets import Label, Input, Button, Static, ProgressBar
|
||||
from textual import work
|
||||
from textual.worker import Worker
|
||||
@ -18,7 +17,7 @@ from skywalker_tui.widgets.spectrum_plot import SpectrumPlot
|
||||
from skywalker_tui.widgets.frequency_table import FrequencyTable
|
||||
|
||||
|
||||
class ScanScreen(Screen):
|
||||
class ScanScreen(Container):
|
||||
"""Multi-phase transponder scanner with progress and results table."""
|
||||
|
||||
DEFAULT_CSS = """
|
||||
@ -111,7 +110,7 @@ class ScanScreen(Screen):
|
||||
yield Button("Scan", id="scan-start-btn", variant="success")
|
||||
yield Button("Stop", id="scan-stop-btn", variant="error")
|
||||
|
||||
def on_unmount(self) -> None:
|
||||
def on_hide(self) -> None:
|
||||
self._stop_scan()
|
||||
|
||||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||||
|
||||
@ -5,8 +5,7 @@ waterfall beneath it. Uses threaded workers for the blocking USB sweep.
|
||||
"""
|
||||
|
||||
from textual.app import ComposeResult
|
||||
from textual.containers import Horizontal, Vertical
|
||||
from textual.screen import Screen
|
||||
from textual.containers import Container, Horizontal, Vertical
|
||||
from textual.widgets import Label, Input, Button, Static, ProgressBar, Checkbox
|
||||
from textual import work
|
||||
from textual.worker import Worker
|
||||
@ -15,7 +14,7 @@ from skywalker_tui.widgets.spectrum_plot import SpectrumPlot
|
||||
from skywalker_tui.widgets.waterfall import WaterfallDisplay
|
||||
|
||||
|
||||
class SpectrumScreen(Screen):
|
||||
class SpectrumScreen(Container):
|
||||
"""Spectrum analyzer with bar chart and optional waterfall."""
|
||||
|
||||
DEFAULT_CSS = """
|
||||
@ -94,11 +93,11 @@ class SpectrumScreen(Screen):
|
||||
yield Button("Sweep", id="spec-sweep-btn", variant="success")
|
||||
yield Button("Stop", id="spec-stop-btn", variant="error")
|
||||
|
||||
def on_mount(self) -> None:
|
||||
if self._bridge.is_demo:
|
||||
def on_show(self) -> None:
|
||||
if self._bridge.is_demo and not self._sweeping:
|
||||
self._start_sweep()
|
||||
|
||||
def on_unmount(self) -> None:
|
||||
def on_hide(self) -> None:
|
||||
self._stop_sweep()
|
||||
|
||||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||||
|
||||
@ -12,8 +12,7 @@ from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from textual.app import ComposeResult
|
||||
from textual.containers import Horizontal, Vertical
|
||||
from textual.screen import Screen
|
||||
from textual.containers import Container, Horizontal, Vertical
|
||||
from textual.widgets import Label, Input, Button, Static, RichLog
|
||||
from textual import work
|
||||
from textual.worker import Worker
|
||||
@ -22,7 +21,7 @@ from skywalker_tui.widgets.signal_gauge import SignalGauge
|
||||
from skywalker_tui.widgets.sparkline_widget import SparklineWidget
|
||||
|
||||
|
||||
class TrackScreen(Screen):
|
||||
class TrackScreen(Container):
|
||||
"""Long-running carrier tracker with event log and export."""
|
||||
|
||||
DEFAULT_CSS = """
|
||||
@ -137,11 +136,11 @@ class TrackScreen(Screen):
|
||||
yield Button("Export CSV", id="trk-csv-btn")
|
||||
yield Button("Export JSONL", id="trk-jsonl-btn")
|
||||
|
||||
def on_mount(self) -> None:
|
||||
if self._bridge.is_demo:
|
||||
def on_show(self) -> None:
|
||||
if self._bridge.is_demo and not self._tracking:
|
||||
self._start_tracking()
|
||||
|
||||
def on_unmount(self) -> None:
|
||||
def on_hide(self) -> None:
|
||||
self._stop_tracking()
|
||||
|
||||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user