参考资料:How to make a tkinter canvas rectangle transparent?
本文以 矩形 为例说明。
方法1:使用 位图填充
from tkinter import Tk, Canvas
root = Tk()
root.geometry("400x400+100+100") # WIDTHxHEIGHT+X+Y
canvas = Canvas(root)
canvas.create_rectangle(20, 50, 200, 300, outline="black",
width=2, fill='red')
canvas.create_rectangle(30, 60, 300, 100, outline="black",
width=2, activefill='skyblue', activestipple="gray50")
canvas.pack(fill='both', expand=1)
root.mainloop()
效果图:
图1 位图填充实现图形透明度
可以看出,效果有那么个意思了,但是,设置透明度并不方便。
方法2 借助 PIL 设置
from tkinter import Tk, Canvas
from PIL import Image, ImageTk
images = [] # to hold the newly created image
def create_rectangle(x1, y1, x2, y2, **kwargs):
if 'alpha' in kwargs:
alpha = int(kwargs.pop('alpha') * 255)
fill = kwargs.pop('fill')
fill = root.winfo_rgb(fill) + (alpha,)
image = Image.new('RGBA', (x2-x1, y2-y1), fill)
images.append(ImageTk.PhotoImage(image))
canvas.create_image(x1, y1, image=images[-1], anchor='nw')
canvas.create_rectangle(x1, y1, x2, y2, **kwargs)
root = Tk()
root.geometry("400x400+100+100") # WIDTHxHEIGHT+X+Y
canvas = Canvas(root)
create_rectangle(10, 10, 200, 100, fill='blue')
create_rectangle(50, 50, 250, 150, fill='green', alpha=.5)
create_rectangle(80, 80, 150, 120, fill='skyblue', alpha=.8)
canvas.pack(fill='both', expand=1)
root.mainloop()
效果如下:
图2 实现真正意义上的透明度设置
也可以改写为类的形式:
from tkinter import Tk, Canvas
from PIL import Image, ImageTk
class Graph(Canvas):
'''Graphic elements are composed of line(segment), rectangle, ellipse, and arc.
'''
def __init__(self, master=None, cnf={}, **kw):
'''The base class of all graphics frames.
:param master: a widget of tkinter or tkinter.ttk.
'''
super().__init__(master, cnf, **kw)
self.rectangle_selector = []
self.tag_bind('current', "<ButtonPress-1>", self.scroll_start)
self.tag_bind('current', "<B1-Motion>", self.scroll_move)
def scroll_start(self, event):
self.scan_mark(event.x, event.y)
def scroll_move(self, event):
self.scan_dragto(event.x, event.y, gain=1)
def create_mask(self, size, alpha, fill):
'''设置透明蒙版'''
fill = self.master.winfo_rgb(fill) + (alpha,)
image = Image.new('RGBA', size, fill)
return image
def draw_rectangle(self, x1, y1, x2, y2, **kw):
if 'alpha' in kw:
size = x2-x1, y2-y1
alpha = int(kw.pop('alpha') * 255)
fill = kw.pop('fill')
image = self.create_mask(size, alpha, fill)
self.rectangle_selector.append(ImageTk.PhotoImage(image))
self.create_image(x1, y1, image=self.rectangle_selector[-1], anchor='nw', tags='mask')
return self.create_rectangle(x1, y1, x2, y2, **kw)
root = Tk()
root.geometry("400x400+100+100") # WIDTHxHEIGHT+X+Y
self = Graph(root)
self.draw_rectangle(10, 10, 200, 100, fill='blue')
self.draw_rectangle(50, 50, 250, 150, fill='green', alpha=.5, tags='selected')
self.draw_rectangle(80, 80, 150, 120, fill='yellow', alpha=.8)
self.pack(fill='both', expand=1)
root.mainloop()