From cd433349571a1774c80d962ddd7300c6d42e4e41 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 29 Oct 2025 14:36:45 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=87=E9=9B=86=E5=8D=A1bug=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- preview.py | 182 +++++++++++++++++++++++++---------------------------- 1 file changed, 84 insertions(+), 98 deletions(-) diff --git a/preview.py b/preview.py index d66636d..bb6fdef 100644 --- a/preview.py +++ b/preview.py @@ -68,60 +68,58 @@ class PreviewWindow: # 存储图像对象 self.photo_objects = {} - def update_frames(): - """更新帧""" - while self.running: - try: - canvas.delete("all") - - # 计算每个预览窗口的位置和大小 - window_width = root.winfo_width() if root.winfo_width() > 1 else 1000 - window_height = root.winfo_height() if root.winfo_height() > 1 else 700 - - cell_width = window_width // columns - cell_height = window_height // rows - - frame_idx = 0 - for idx in self.caps.keys(): - if idx in self.frames: - row = frame_idx // columns - col = frame_idx % columns - - x = col * cell_width - y = row * cell_height - - # 调整图像大小 - frame = self.frames[idx] - h, w = frame.shape[:2] - scale = min(cell_width / w, cell_height / h) * 0.9 - new_w = int(w * scale) - new_h = int(h * scale) - - resized_frame = cv2.resize(frame, (new_w, new_h)) - - # 转换为PIL图像 - pil_image = Image.fromarray(resized_frame) - photo = ImageTk.PhotoImage(image=pil_image) - self.photo_objects[idx] = photo - - # 绘制图像 - center_x = x + cell_width // 2 - center_y = y + cell_height // 2 - canvas.create_image(center_x, center_y, image=photo, anchor='center') - - # 绘制标签 - name = self.caps[idx]['name'] - canvas.create_text(center_x, y + 20, text=name, fill='white', font=('Arial', 12, 'bold')) - - frame_idx += 1 - - canvas.update() - tk._default_root.update_idletasks() - except Exception as e: - print(f"更新帧错误: {e}") - - import time - time.sleep(0.03) # 约30fps + def update_frames_once(): + """在主线程中更新一帧(使用after循环)""" + if not self.running: + return + try: + canvas.delete("all") + + # 计算每个预览窗口的位置和大小 + window_width = root.winfo_width() if root.winfo_width() > 1 else 1000 + window_height = root.winfo_height() if root.winfo_height() > 1 else 700 + + cell_width = window_width // columns + cell_height = window_height // rows + + frame_idx = 0 + for idx in self.caps.keys(): + if idx in self.frames: + row = frame_idx // columns + col = frame_idx % columns + + x = col * cell_width + y = row * cell_height + + # 调整图像大小 + frame = self.frames[idx] + h, w = frame.shape[:2] + scale = min(cell_width / w, cell_height / h) * 0.9 + new_w = int(w * scale) + new_h = int(h * scale) + + resized_frame = cv2.resize(frame, (new_w, new_h)) + + # 转换为PIL图像 + pil_image = Image.fromarray(resized_frame) + photo = ImageTk.PhotoImage(image=pil_image) + # 保持引用,避免被GC + self.photo_objects[idx] = photo + + # 绘制图像 + center_x = x + cell_width // 2 + center_y = y + cell_height // 2 + canvas.create_image(center_x, center_y, image=photo, anchor='center') + + # 绘制标签 + name = self.caps[idx]['name'] + canvas.create_text(center_x, y + 20, text=name, fill='white', font=('Arial', 12, 'bold')) + + frame_idx += 1 + except Exception as e: + print(f"更新帧错误: {e}") + # 约30fps + root.after(33, update_frames_once) def on_canvas_click(event): """点击画布事件""" @@ -141,9 +139,8 @@ class PreviewWindow: canvas.bind('', on_canvas_click) - # 启动更新线程 - update_thread = threading.Thread(target=update_frames, daemon=True) - update_thread.start() + # 使用after在主线程中循环刷新 + root.after(33, update_frames_once) def on_closing(): """关闭窗口""" @@ -160,7 +157,7 @@ class PreviewWindow: if self.large_window is not None and self.large_window.winfo_exists(): self.large_window.destroy() - self.large_window = tk.Tk() + self.large_window = tk.Toplevel() self.large_window.title(f"放大视图 - {self.caps[idx]['name']}") self.large_window.geometry("1280x720") @@ -169,46 +166,35 @@ class PreviewWindow: photo_obj = {} - def update_large_frame(): - """更新大窗口帧""" - while self.running: - try: - if idx in self.frames and self.large_window.winfo_exists(): - canvas.delete("all") - - frame = self.frames[idx] - h, w = frame.shape[:2] - - # 调整到窗口大小 - window_width = self.large_window.winfo_width() if self.large_window.winfo_width() > 1 else 1280 - window_height = self.large_window.winfo_height() if self.large_window.winfo_height() > 1 else 720 - - scale = min(window_width / w, window_height / h) - new_w = int(w * scale) - new_h = int(h * scale) - - resized_frame = cv2.resize(frame, (new_w, new_h)) - pil_image = Image.fromarray(resized_frame) - photo = ImageTk.PhotoImage(image=pil_image) - photo_obj['img'] = photo - - canvas.delete("all") - canvas.create_image(window_width // 2, window_height // 2, image=photo, anchor='center') - - self.large_window.update() - else: - break - except Exception as e: - print(f"更新大窗口错误: {e}") - break - - import time - time.sleep(0.03) - - update_thread = threading.Thread(target=update_large_frame, daemon=True) - update_thread.start() - - self.large_window.mainloop() + def update_large_once(): + if not self.running or not self.large_window.winfo_exists(): + return + try: + if idx in self.frames: + canvas.delete("all") + + frame = self.frames[idx] + h, w = frame.shape[:2] + + # 调整到窗口大小 + window_width = self.large_window.winfo_width() if self.large_window.winfo_width() > 1 else 1280 + window_height = self.large_window.winfo_height() if self.large_window.winfo_height() > 1 else 720 + + scale = min(window_width / w, window_height / h) + new_w = int(w * scale) + new_h = int(h * scale) + + resized_frame = cv2.resize(frame, (new_w, new_h)) + pil_image = Image.fromarray(resized_frame) + photo = ImageTk.PhotoImage(image=pil_image) + photo_obj['img'] = photo + + canvas.create_image(window_width // 2, window_height // 2, image=photo, anchor='center') + except Exception as e: + print(f"更新大窗口错误: {e}") + self.large_window.after(33, update_large_once) + + self.large_window.after(33, update_large_once) def run(self): """运行预览"""