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,17 +23,20 @@ from config import LOGGING_CONFIG
def main():
"""Initializes and runs the application."""
import logging
logging.getLogger('matplotlib').setLevel(logging.WARNING)
app = MainView()
# Setup the global logging system, connecting it to the GUI's main loop
setup_basic_logging(app, LOGGING_CONFIG)
# Now that the logging system is active, add the handler for the GUI widget
add_tkinter_handler(app.log_text_widget, LOGGING_CONFIG)
logger = get_logger(__name__)
logger.info("Application starting up.")
app.mainloop()

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.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)
# I bottoni Add/Remove/Edit sono gestiti dal frame stesso
# --- Logs Frame ---
log_frame_container = ttk.LabelFrame(v_pane, text="Logs")
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.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):
self.conn_status_canvas.delete("all")
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]):
"""
Updates the positions of targets on the PPI display.
Args:
targets: A list of Target objects to display.
Aggiorna la posizione dei target sulla PPI e mostra l'ID accanto al punto. Tooltip con ID al passaggio del mouse.
"""
# 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:
self.active_targets = [t for t in targets if t.active]
# Clear previously drawn targets
# Rimuovi artisti precedenti
for artist in self.target_artists:
artist.remove()
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', []):
# Target position in polar
r1 = target.range_nm
th1 = np.deg2rad(target.azimuth_deg)
# Plot the target's center dot
dot, = self.ax.plot(th1, r1, 'o', markersize=5, color='red')
# Punto del target
dot, = self.ax.plot(th1, r1, 'o', markersize=5, color='red', picker=5)
self.target_artists.append(dot)
self._target_dots.append((dot, target))
# --- Calculate and plot heading vector ---
# Convert target polar to cartesian
# Vettore heading
x1 = r1 * np.sin(th1)
y1 = r1 * np.cos(th1)
# Calculate heading vector components
h_rad = np.deg2rad(target.heading_deg)
dx = vector_len * np.sin(h_rad)
dy = vector_len * np.cos(h_rad)
# Calculate end point of the vector in cartesian
x2, y2 = x1 + dx, y1 + dy
# Convert end point back to polar
r2 = np.sqrt(x2**2 + y2**2)
th2 = np.arctan2(x2, y2)
# Plot the heading line
line, = self.ax.plot([th1, th2], [r1, r2], color='red', linewidth=1.2)
self.target_artists.append(line)
# Redraw the canvas to show the changes
self.canvas.draw()
# 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()
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."""
def __init__(self, master):
def __init__(self, master, targets_changed_callback=None):
super().__init__(master, text="Target List")
self.targets_cache = []
self.targets_changed_callback = targets_changed_callback
# --- Treeview for Targets ---
columns = ("id", "range", "az", "vel", "hdg", "alt")
self.tree = ttk.Treeview(self, columns=columns, show="headings")
@ -72,6 +73,8 @@ class TargetListFrame(ttk.LabelFrame):
if add_window.new_target:
self.targets_cache.append(add_window.new_target)
self.update_target_list(self.targets_cache)
if self.targets_changed_callback:
self.targets_changed_callback(self.targets_cache)
def _on_remove_click(self):
selected = self.tree.focus()
@ -93,6 +96,8 @@ class TargetListFrame(ttk.LabelFrame):
# Rimuovi il target dalla lista
self.targets_cache = [t for t in getattr(self, 'targets_cache', []) if t.target_id != target_id]
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à)
self.tree.bind('<Double-1>', self._on_double_click)
@ -127,7 +132,8 @@ class TargetListFrame(ttk.LabelFrame):
return
# Apri la finestra di modifica
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)
edit_window.id_var.set(target_id)
edit_window.id_spinbox.config(state='disabled')
@ -149,6 +155,8 @@ class TargetListFrame(ttk.LabelFrame):
target.altitude_ft = edit_window.new_target.altitude_ft
# Aggiorna la tabella
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):
# Usa identify_row per trovare la riga cliccata