如何在tkinter的canvas上实现局部矩形透明效果以开发拖拽截图工具
Tkinter Canvas 局部透明实现方案
要实现全屏半透明蒙层+拖拽区域挖空的效果,核心是利用Tkinter的窗口透明色属性实现,这是最适配截图工具场景的实现方式:
实现步骤
- 首先创建全屏无边界顶层窗口,开启窗口透明色通道:
import tkinter as tk root = tk.Tk() # 去掉窗口边框 root.overrideredirect(True) # 铺满整个屏幕 root.geometry(f"{root.winfo_screenwidth()}x{root.winfo_screenheight()}+0+0") # 设置窗口整体半透度,叠加蒙层底色后就是你要的半透明效果 root.attributes("-alpha", 0.6) # 关键配置:指定#ffffff为窗口的完全透明色,所有这个颜色的区域会直接穿透 root.attributes("-transparentcolor", "#ffffff")
- 接着在窗口上铺满Canvas,作为半透明蒙层的载体:
# Canvas背景选深灰色,和窗口半透属性叠加后就是暗灰色蒙层效果,highlightthickness去掉默认边框 canvas = tk.Canvas(root, bg="#333333", highlightthickness=0) canvas.pack(fill=tk.BOTH, expand=True)
- 最后绑定鼠标事件,拖拽时动态绘制填充色为
#ffffff的矩形,这个矩形区域就会自动变成完全透明,相当于在蒙层上挖洞:
start_x = start_y = 0 select_rect = None def on_mouse_press(event): global start_x, start_y, select_rect start_x, start_y = event.x, event.y # 清空上一次的选择框 if select_rect: canvas.delete(select_rect) # 新绘制选框,填充色为我们指定的透明色,外框用红色方便看清边界 select_rect = canvas.create_rectangle(start_x, start_y, start_x, start_y, fill="#ffffff", outline="red", width=1) def on_mouse_drag(event): global select_rect # 实时更新选框坐标 canvas.coords(select_rect, start_x, start_y, event.x, event.y) # 绑定鼠标事件 canvas.bind("<ButtonPress-1>", on_mouse_press) canvas.bind("<B1-Motion>", on_mouse_drag) root.mainloop()
注意事项
- 该方案依赖系统窗口层的透明色属性,Windows、主流版本MacOS都原生支持,Linux环境需要先开启桌面合成器
- 如果需要更强的跨平台兼容性,可以改用PIL生成带透明通道的全屏图片,把选中区域的alpha值设为0后贴到Canvas上,只是性能比上述方案稍低
- 拖拽结束后直接获取选框的坐标,调用
PIL.ImageGrab抓取对应坐标范围的屏幕内容,就能得到最终的截图结果
内容的提问来源于stack exchange,提问作者Leonard Li
相关产品推荐
相关产品推荐

