fix gui and button fuction

This commit is contained in:
VALLONGOL 2025-10-02 15:19:18 +02:00
parent 4797533386
commit 08aa827cd7
4 changed files with 68 additions and 32 deletions

View File

@ -23,6 +23,9 @@ from config import LOGGING_CONFIG
def main(): def main():
"""Initializes and runs the application.""" """Initializes and runs the application."""
import logging
logging.getLogger('matplotlib').setLevel(logging.WARNING)
app = MainView() app = MainView()
# Setup the global logging system, connecting it to the GUI's main loop # Setup the global logging system, connecting it to the GUI's main loop

View File

@ -77,14 +77,19 @@ class MainView(tk.Tk):
self.scenario_controls = ScenarioControlsFrame(left_frame, load_scenario_command=self._on_load_scenario, save_as_command=self._on_save_scenario_as, update_command=self._on_update_scenario, delete_command=self._on_delete_scenario) self.scenario_controls = ScenarioControlsFrame(left_frame, load_scenario_command=self._on_load_scenario, save_as_command=self._on_save_scenario_as, update_command=self._on_update_scenario, delete_command=self._on_delete_scenario)
self.scenario_controls.pack(fill=tk.X, expand=False, padx=5, pady=(5, 5)) self.scenario_controls.pack(fill=tk.X, expand=False, padx=5, pady=(5, 5))
self.target_list = TargetListFrame(left_frame) self.target_list = TargetListFrame(left_frame, targets_changed_callback=self._on_targets_changed)
self.target_list.pack(fill=tk.BOTH, expand=True, padx=5) self.target_list.pack(fill=tk.BOTH, expand=True, padx=5)
# I bottoni Add/Remove/Edit sono gestiti dal frame stesso
# --- Logs Frame ---
log_frame_container = ttk.LabelFrame(v_pane, text="Logs") log_frame_container = ttk.LabelFrame(v_pane, text="Logs")
v_pane.add(log_frame_container, weight=1) v_pane.add(log_frame_container, weight=1)
self.log_text_widget = scrolledtext.ScrolledText(log_frame_container, state=tk.DISABLED, wrap=tk.WORD, font=("Consolas", 9)) self.log_text_widget = scrolledtext.ScrolledText(log_frame_container, state=tk.DISABLED, wrap=tk.WORD, font=("Consolas", 9))
self.log_text_widget.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) self.log_text_widget.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
def _on_targets_changed(self, targets):
# Called by TargetListFrame when targets are changed
self.ppi_widget.update_targets(targets)
def _draw_conn_status_indicator(self, connected: bool): def _draw_conn_status_indicator(self, connected: bool):
self.conn_status_canvas.delete("all") self.conn_status_canvas.delete("all")
color = "#2ecc40" if connected else "#e74c3c" # green or red color = "#2ecc40" if connected else "#e74c3c" # green or red

View File

@ -108,52 +108,72 @@ class PPIDisplay(ttk.Frame):
def update_targets(self, targets: List[Target]): def update_targets(self, targets: List[Target]):
""" """
Updates the positions of targets on the PPI display. Aggiorna la posizione dei target sulla PPI e mostra l'ID accanto al punto. Tooltip con ID al passaggio del mouse.
Args:
targets: A list of Target objects to display.
""" """
# If an empty list is passed, it means we just want to redraw existing targets
# (e.g., after a zoom change), not clear them.
if targets: if targets:
self.active_targets = [t for t in targets if t.active] self.active_targets = [t for t in targets if t.active]
# Clear previously drawn targets # Rimuovi artisti precedenti
for artist in self.target_artists: for artist in self.target_artists:
artist.remove() artist.remove()
self.target_artists.clear() self.target_artists.clear()
vector_len = self.range_var.get() / 25 # Length of heading vector relative to current view # Rimuovi eventuali tooltips precedenti
if hasattr(self, 'tooltips'):
for tip in self.tooltips:
tip.remove()
self.tooltips = []
vector_len = self.range_var.get() / 25
self._target_dots = []
for target in getattr(self, 'active_targets', []): for target in getattr(self, 'active_targets', []):
# Target position in polar
r1 = target.range_nm r1 = target.range_nm
th1 = np.deg2rad(target.azimuth_deg) th1 = np.deg2rad(target.azimuth_deg)
# Punto del target
# Plot the target's center dot dot, = self.ax.plot(th1, r1, 'o', markersize=5, color='red', picker=5)
dot, = self.ax.plot(th1, r1, 'o', markersize=5, color='red')
self.target_artists.append(dot) self.target_artists.append(dot)
self._target_dots.append((dot, target))
# --- Calculate and plot heading vector --- # Vettore heading
# Convert target polar to cartesian
x1 = r1 * np.sin(th1) x1 = r1 * np.sin(th1)
y1 = r1 * np.cos(th1) y1 = r1 * np.cos(th1)
# Calculate heading vector components
h_rad = np.deg2rad(target.heading_deg) h_rad = np.deg2rad(target.heading_deg)
dx = vector_len * np.sin(h_rad) dx = vector_len * np.sin(h_rad)
dy = vector_len * np.cos(h_rad) dy = vector_len * np.cos(h_rad)
# Calculate end point of the vector in cartesian
x2, y2 = x1 + dx, y1 + dy x2, y2 = x1 + dx, y1 + dy
# Convert end point back to polar
r2 = np.sqrt(x2**2 + y2**2) r2 = np.sqrt(x2**2 + y2**2)
th2 = np.arctan2(x2, y2) th2 = np.arctan2(x2, y2)
# Plot the heading line
line, = self.ax.plot([th1, th2], [r1, r2], color='red', linewidth=1.2) line, = self.ax.plot([th1, th2], [r1, r2], color='red', linewidth=1.2)
self.target_artists.append(line) self.target_artists.append(line)
# Redraw the canvas to show the changes # Gestione tooltip
def on_motion(event):
# Mostra hint se il mouse è vicino a un punto target
if event.inaxes != self.ax:
if hasattr(self, '_tooltip_label') and self._tooltip_label:
self._tooltip_label.place_forget()
self._tooltip_label = None
return
found = False
for dot, target in self._target_dots:
cont, _ = dot.contains(event)
if cont:
# Usa la posizione del mouse relativa al widget Tkinter
self._show_tooltip(event.x + 10, event.y + 10, f"ID: {target.target_id}")
found = True
break
if not found and hasattr(self, '_tooltip_label') and self._tooltip_label:
self._tooltip_label.place_forget()
self._tooltip_label = None
self.canvas.mpl_connect('motion_notify_event', on_motion)
self._tooltip_label = None
self.canvas.draw() self.canvas.draw()
def _show_tooltip(self, x, y, text):
# Mostra un tooltip Tkinter sopra la canvas, centrato sul punto target
if self._tooltip_label:
self._tooltip_label.place_forget()
self._tooltip_label = tk.Label(self.canvas.get_tk_widget(), text=text, bg='yellow', fg='black', font=('Consolas', 9), relief='solid', borderwidth=1)
self._tooltip_label.place(x=x, y=y)

View File

@ -15,9 +15,10 @@ class TargetListFrame(ttk.LabelFrame):
"""Frame for displaying and managing the list of targets.""" """Frame for displaying and managing the list of targets."""
def __init__(self, master): def __init__(self, master, targets_changed_callback=None):
super().__init__(master, text="Target List") super().__init__(master, text="Target List")
self.targets_cache = [] self.targets_cache = []
self.targets_changed_callback = targets_changed_callback
# --- Treeview for Targets --- # --- Treeview for Targets ---
columns = ("id", "range", "az", "vel", "hdg", "alt") columns = ("id", "range", "az", "vel", "hdg", "alt")
self.tree = ttk.Treeview(self, columns=columns, show="headings") self.tree = ttk.Treeview(self, columns=columns, show="headings")
@ -72,6 +73,8 @@ class TargetListFrame(ttk.LabelFrame):
if add_window.new_target: if add_window.new_target:
self.targets_cache.append(add_window.new_target) self.targets_cache.append(add_window.new_target)
self.update_target_list(self.targets_cache) self.update_target_list(self.targets_cache)
if self.targets_changed_callback:
self.targets_changed_callback(self.targets_cache)
def _on_remove_click(self): def _on_remove_click(self):
selected = self.tree.focus() selected = self.tree.focus()
@ -93,6 +96,8 @@ class TargetListFrame(ttk.LabelFrame):
# Rimuovi il target dalla lista # Rimuovi il target dalla lista
self.targets_cache = [t for t in getattr(self, 'targets_cache', []) if t.target_id != target_id] self.targets_cache = [t for t in getattr(self, 'targets_cache', []) if t.target_id != target_id]
self.update_target_list(self.targets_cache) self.update_target_list(self.targets_cache)
if self.targets_changed_callback:
self.targets_changed_callback(self.targets_cache)
# Bind doppio click su una riga (usando identify_row per maggiore affidabilità) # Bind doppio click su una riga (usando identify_row per maggiore affidabilità)
self.tree.bind('<Double-1>', self._on_double_click) self.tree.bind('<Double-1>', self._on_double_click)
@ -127,7 +132,8 @@ class TargetListFrame(ttk.LabelFrame):
return return
# Apri la finestra di modifica # Apri la finestra di modifica
from .add_target_window import AddTargetWindow from .add_target_window import AddTargetWindow
edit_window = AddTargetWindow(self, existing_ids=[target_id]) # Pass all other IDs except the one being edited
edit_window = AddTargetWindow(self, existing_ids=[t.target_id for t in self.targets_cache if t.target_id != target_id])
# Precompila i dati (tranne l'id) # Precompila i dati (tranne l'id)
edit_window.id_var.set(target_id) edit_window.id_var.set(target_id)
edit_window.id_spinbox.config(state='disabled') edit_window.id_spinbox.config(state='disabled')
@ -149,6 +155,8 @@ class TargetListFrame(ttk.LabelFrame):
target.altitude_ft = edit_window.new_target.altitude_ft target.altitude_ft = edit_window.new_target.altitude_ft
# Aggiorna la tabella # Aggiorna la tabella
self.update_target_list(self.targets_cache) self.update_target_list(self.targets_cache)
if self.targets_changed_callback:
self.targets_changed_callback(self.targets_cache)
def _on_double_click(self, event): def _on_double_click(self, event):
# Usa identify_row per trovare la riga cliccata # Usa identify_row per trovare la riga cliccata