diff --git a/VideoReceiverSFP/gui/viewer_sar.py b/VideoReceiverSFP/gui/viewer_sar.py index d3aeebf..d639eed 100644 --- a/VideoReceiverSFP/gui/viewer_sar.py +++ b/VideoReceiverSFP/gui/viewer_sar.py @@ -41,11 +41,10 @@ class SfpSarViewer: img_frame = ttk.Frame(main) img_frame.grid(row=0, column=0, sticky="nsew") - # Use Canvas to ensure fixed size display + # Use Canvas to ensure fixed size display; we'll draw images into it self._img_canvas = tk.Canvas(img_frame, width=484, height=484, bg="black", highlightthickness=0) self._img_canvas.pack(fill="both", expand=True) - self._img_label = tk.Label(self._img_canvas, bg="black") - self._img_canvas.create_window(242, 242, window=self._img_label) + self._canvas_image_id = None # Right controls ctrl_frame = ttk.Labelframe(main, text="SAR Controls", padding=8) @@ -278,14 +277,12 @@ class SfpSarViewer: except Exception: disp_img = img - # Resize to fit the label widget while preserving aspect ratio. + # Resize to fit the canvas while preserving aspect ratio. try: - w = self._img_label.winfo_width() - h = self._img_label.winfo_height() - # If widget not yet laid out, winfo_ reports 1; use geometry fallback + w = self._img_canvas.winfo_width() + h = self._img_canvas.winfo_height() if w > 2 and h > 2: max_size = (max(1, w), max(1, h)) - # Resize the display image copy (disp_img) not the raw image try: disp_img = disp_img.copy() disp_img.thumbnail(max_size, Image.LANCZOS) @@ -301,27 +298,35 @@ class SfpSarViewer: except Exception: pass - # Save a debug copy - try: - dumps_dir = os.path.join(os.getcwd(), 'dumps') - os.makedirs(dumps_dir, exist_ok=True) - debug_path = os.path.join(dumps_dir, 'VideoReceiverSFP_sar_last.png') - try: - disp_img.save(debug_path) - except Exception: - img.save(debug_path) - except Exception: - pass - try: return ImageTk.PhotoImage(disp_img, master=self._root) except Exception: - # Fallback to default behavior return ImageTk.PhotoImage(disp_img) except Exception: logging.exception("SfpSarViewer: failed to build tk image") return None + def _draw_image_on_canvas(self, photo_image: ImageTk.PhotoImage) -> None: + try: + # Keep reference to avoid GC + self._last_photoimage = photo_image + # Draw into canvas, centered + if self._canvas_image_id is None: + self._canvas_image_id = self._img_canvas.create_image( + self._img_canvas.winfo_width() // 2, + self._img_canvas.winfo_height() // 2, + image=self._last_photoimage, + anchor='center' + ) + else: + self._img_canvas.itemconfigure(self._canvas_image_id, image=self._last_photoimage) + # Recenter in case canvas size changed + self._img_canvas.coords(self._canvas_image_id, + self._img_canvas.winfo_width() // 2, + self._img_canvas.winfo_height() // 2) + except Exception: + pass + def _poll(self): try: frame = None @@ -337,7 +342,7 @@ class SfpSarViewer: tkimg = self._build_tk_image(frame) if tkimg is not None: self._photo = tkimg - self._img_label.config(image=self._photo) + self._draw_image_on_canvas(self._photo) elif params_changed: # No new frame but params changed: refresh current image self._refresh_current_image() @@ -384,8 +389,8 @@ class SfpSarViewer: except Exception: pil = raw try: - w = self._img_label.winfo_width() - h = self._img_label.winfo_height() + w = self._img_canvas.winfo_width() + h = self._img_canvas.winfo_height() if w > 2 and h > 2: pil = pil.copy() pil.thumbnail((max(1, w), max(1, h)), Image.LANCZOS) @@ -398,8 +403,8 @@ class SfpSarViewer: with self._lock: self._photo = tkimg try: - self._img_label.config(image=self._photo) - self._img_label.update_idletasks() + self._draw_image_on_canvas(self._photo) + self._img_canvas.update_idletasks() except Exception: pass except Exception: