采集卡bug修复
This commit is contained in:
64
preview.py
64
preview.py
@@ -322,11 +322,11 @@ class PreviewWindow:
|
||||
pil_image = Image.fromarray(resized_frame)
|
||||
photo = ImageTk.PhotoImage(image=pil_image)
|
||||
|
||||
# 多重引用保护,防止被GC回收
|
||||
self.photo_objects[idx] = photo # 按索引保存
|
||||
self.photo_objects_list.append(photo) # 在列表中保存(防止GC)
|
||||
# 保存引用(按索引保存,方便查找)
|
||||
self.photo_objects[idx] = photo
|
||||
|
||||
images_to_draw.append((photo, center_x, center_y))
|
||||
# 添加到绘制列表(在列表中保存引用,防止GC)
|
||||
images_to_draw.append((photo, center_x, center_y, idx))
|
||||
texts_to_draw.append((center_x, y + 15, name, 'white'))
|
||||
|
||||
frame_idx += 1
|
||||
@@ -353,31 +353,57 @@ class PreviewWindow:
|
||||
print(f" 当前保存的照片对象数量: {len(self.photo_objects_list)}")
|
||||
|
||||
if images_to_draw:
|
||||
# 创建一个临时列表保存所有photo引用,防止在绘制时被GC
|
||||
photos_to_keep = []
|
||||
for i, (photo, x, y) in enumerate(images_to_draw):
|
||||
# 先收集所有photo对象到列表中,确保引用不丢失
|
||||
photos_current_frame = []
|
||||
|
||||
for i, item in enumerate(images_to_draw):
|
||||
if len(item) == 4:
|
||||
photo, x, y, idx = item
|
||||
else:
|
||||
# 兼容旧格式(如果还有的话)
|
||||
photo, x, y = item[:3]
|
||||
idx = None
|
||||
|
||||
try:
|
||||
# 确保坐标在画布范围内
|
||||
if 0 <= x <= canvas_width and 0 <= y <= canvas_height:
|
||||
# 在绘制前保存引用
|
||||
photos_to_keep.append(photo)
|
||||
# 先保存引用到列表(防止GC)
|
||||
photos_current_frame.append(photo)
|
||||
|
||||
# 然后绘制
|
||||
canvas.create_image(x, y, image=photo, anchor='center')
|
||||
|
||||
if self.debug_count <= 3 and i == 0:
|
||||
print(f" 绘制图像 #{i} 到位置 ({x}, {y}), photo id: {id(photo)}")
|
||||
print(f" 绘制图像 #{i} (idx={idx}) 到位置 ({x}, {y})")
|
||||
else:
|
||||
if self.debug_count <= 3:
|
||||
print(f" ⚠️ 图像 #{i} 位置 ({x}, {y}) 超出画布范围")
|
||||
except Exception as e:
|
||||
print(f" 绘制图像 #{i} 错误: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
error_msg = str(e).lower()
|
||||
print(f" ❌ 绘制图像 #{i} 时出错: {type(e).__name__}: {e}")
|
||||
|
||||
if "pyimage" in error_msg:
|
||||
# PhotoImage 对象被 GC 了,尝试恢复
|
||||
if self.debug_count <= 5:
|
||||
print(f" ⚠️ PhotoImage 对象丢失,尝试从字典恢复 (idx={idx})")
|
||||
if idx is not None and idx in self.photo_objects:
|
||||
try:
|
||||
photo = self.photo_objects[idx]
|
||||
photos_current_frame.append(photo)
|
||||
canvas.create_image(x, y, image=photo, anchor='center')
|
||||
if self.debug_count <= 5:
|
||||
print(f" ✅ 已从字典恢复并重新绘制")
|
||||
except Exception as e2:
|
||||
if self.debug_count <= 5:
|
||||
print(f" ❌ 恢复失败: {e2}")
|
||||
else:
|
||||
# 其他类型的错误,打印完整堆栈
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
# 确保照片对象不被回收(保存引用到实例变量)
|
||||
# 只保留最近的一批照片对象,避免内存泄漏
|
||||
self.photo_objects_list = photos_to_keep[:] # 复制列表
|
||||
# 限制列表大小,只保留最近的20个对象
|
||||
if len(self.photo_objects_list) > 20:
|
||||
self.photo_objects_list = self.photo_objects_list[-20:]
|
||||
# 保存当前帧的所有photo引用(替换旧的列表,只保留当前帧)
|
||||
# 这样确保正在显示的photo对象不会被GC
|
||||
self.photo_objects_list = photos_current_frame[:] # 复制列表
|
||||
else:
|
||||
# 如果没有图像,至少显示一些提示
|
||||
if self.debug_count <= 3:
|
||||
|
||||
Reference in New Issue
Block a user