如何在Tkinter中实现鼠标在摄像头画面上绘制的功能?
问题本质
你每轮更新都调用canvas.create_image新增图像元素,Canvas中新创建的元素默认层级高于所有已有元素,相当于每10ms就往画布最顶层覆盖一张新的摄像头画面,之前绘制的内容自然会被遮挡,调整已有元素的层级无法解决,因为每次都会生成更高层级的新图像。
可行解决方案
以下两种方案按需选择即可:
方案1:复用图像元素(改造成本最低)
仅在第一次更新时创建图像元素,后续直接更新已有元素的内容,不会新增层级,绘制的内容会一直保留在画面上层。
修改后的update方法代码:
def update(self): isTrue, frame = self.vid.getFrame() if isTrue: self.photo = ImageTk.PhotoImage(image=PIL.Image.fromarray(frame)) # 首次运行创建图像元素,后续直接更新内容 if not hasattr(self, 'image'): self.image = self.canvas.create_image(0, 0, image=self.photo, anchor=tk.NW) else: self.canvas.itemconfig(self.image, image=self.photo) self.window.after(10, self.update)
方案2:双画布分层(更利于后续扩展)
如果后续需要对绘制内容做单独清空、显隐、保存等操作,推荐用分层渲染结构:
- 创建底层Canvas专门渲染摄像头画面
- 再创建一个背景透明的顶层Canvas,尺寸和位置和底层完全对齐,所有绘制操作都在顶层Canvas执行
- 两层完全独立,摄像头更新不会影响顶层的绘制内容
初始化参考代码:
# 底层画布:放摄像头画面 self.canvas_cam = tk.Canvas(self.window, width=画面宽度, height=画面高度) self.canvas_cam.pack() # 顶层画布:透明背景,专门做绘制,和底层完全对齐 self.canvas_draw = tk.Canvas(self.window, width=画面宽度, height=画面高度, bg="", highlightthickness=0) self.canvas_draw.place(x=0, y=0)
后续update方法操作self.canvas_cam,paint方法操作self.canvas_draw即可。
内容的提问来源于stack exchange,提问作者KDog
相关产品推荐
相关产品推荐

