如何批量填充Tkinter Canvas中多基础形状构成的图形?求FloodFill替代方案
在Tkinter中实现类似Pascal FloodFill的填充功能
Tkinter本身没有内置的FloodFill(泛洪填充)函数,针对你用圆弧、线条绘制的图形,有两种可行的填充方案:
方案1:重构图形为闭合形状(最简便)
如果你的图形可以被定义为闭合路径,直接使用Tkinter内置的填充参数即可,无需额外依赖。
比如将原来的style=ARC(仅轮廓)改为style=CHORD(闭合弧),并添加fill参数指定填充颜色。调整后的示例代码:
from tkinter import * root=Tk() c=Canvas(root,width=700,height=500,bg='blue',cursor="pencil") # 改为闭合CHORD样式并填充 c.create_arc(250,175,300,200,outline='white',style=CHORD,start=0,extent=180,fill='yellow')#1 c.create_arc(200,175,250,200,outline='white',style=CHORD,start=0,extent=180,fill='yellow')#2 c.create_arc(150,175,200,200,outline='white',style=CHORD,start=0,extent=180,fill='yellow')#3 c.create_arc(100,175,150,200,outline='white',style=CHORD,start=0,extent=180,fill='yellow')#4 c.create_arc(100,100,300,270,outline='white',style=CHORD,start=0,extent=180,fill='yellow')#umbrella c.create_line(200,185,200,300,fill='white') c.create_arc(200,275,250,325,outline='white',style=CHORD,start=180,extent=180,fill='yellow') c.pack() root.mainloop()
注意:调整了圆弧的坐标顺序(确保
x1<x2,y1<y2),Tkinter会自动修正逆序坐标,但显式写正确更清晰。
方案2:像素级泛洪填充(适配线条组成的封闭区域)
如果你的图形是由线条/弧组成的视觉封闭区域但无法直接转为闭合形状,可以借助PIL(Pillow)库实现类似FloodFill的功能,步骤如下:
- 先安装Pillow:
pip install pillow - 使用
ImageDraw.floodfill对Canvas内容进行像素级填充,示例代码:
from tkinter import * from PIL import Image, ImageDraw, ImageTk root = Tk() c = Canvas(root, width=700, height=500, bg='blue', cursor="pencil") # 绘制原图形 c.create_arc(300,200,250,175,outline='white',style=ARC,start=0,extent=180)#1 c.create_arc(250,200,200,175,outline='white',style=ARC,start=0,extent=180)#2 c.create_arc(200,200,150,175,outline='white',style=ARC,start=0,extent=180)#3 c.create_arc(150,200,100,175,outline='white',style=ARC,start=0,extent=180)#4 c.create_arc(100,100,300,270,outline='white',style=ARC,start=0,extent=180)#umbrella c.create_line(200,185,200,300,fill='white') c.create_arc(200,325,250,275,outline='white',style=ARC,start=180,extent=180) c.pack() def flood_fill(event): # 获取点击坐标 x, y = event.x, event.y # 创建与Canvas同尺寸的PIL图像 img = Image.new('RGB', (700, 500), 'blue') draw = ImageDraw.Draw(img) # 将Canvas图形重绘到PIL图像(确保坐标匹配) draw.arc((250,175,300,200), 0, 180, fill='white') draw.arc((200,175,250,200), 0, 180, fill='white') draw.arc((150,175,200,200), 0, 180, fill='white') draw.arc((100,175,150,200), 0, 180, fill='white') draw.arc((100,100,300,270), 0, 180, fill='white') draw.line((200,185,200,300), fill='white', width=1) draw.arc((200,275,250,325), 180, 360, fill='white') # 执行泛洪填充:点击位置、填充色、边界色 draw.floodfill((x,y), 'yellow', border='white') # 转为Tkinter可用的图像并显示 tk_img = ImageTk.PhotoImage(img) c.create_image(0,0, image=tk_img, anchor=NW) c.image = tk_img # 保存引用避免被垃圾回收 # 绑定鼠标左键点击事件触发填充 c.bind('<Button-1>', flood_fill) root.mainloop()
运行后点击图形内的封闭区域,即可完成填充。
内容的提问来源于stack exchange,提问作者Svyaga Inc.
相关产品推荐
相关产品推荐

