不幸的是,当图片被调整大小时效果不佳。
以下是一个使用canvas制作的圆角按钮示例,即使被调整大小也能正常显示。
import tkinter as tk
class RoundedButton(tk.Canvas):
def __init__(self, master=None, text:str="", radius=25, btnforeground="#000000", btnbackground="#ffffff", clicked=None, *args, **kwargs):
super(RoundedButton, self).__init__(master, *args, **kwargs)
self.config(bg=self.master["bg"])
self.btnbackground = btnbackground
self.clicked = clicked
self.radius = radius
self.rect = self.round_rectangle(0, 0, 0, 0, tags="button", radius=radius, fill=btnbackground)
self.text = self.create_text(0, 0, text=text, tags="button", fill=btnforeground, font=("Times", 30), justify="center")
self.tag_bind("button", "<ButtonPress>", self.border)
self.tag_bind("button", "<ButtonRelease>", self.border)
self.bind("<Configure>", self.resize)
text_rect = self.bbox(self.text)
if int(self["width"]) < text_rect[2]-text_rect[0]:
self["width"] = (text_rect[2]-text_rect[0]) + 10
if int(self["height"]) < text_rect[3]-text_rect[1]:
self["height"] = (text_rect[3]-text_rect[1]) + 10
def round_rectangle(self, x1, y1, x2, y2, radius=25, update=False, **kwargs):
points = [x1+radius, y1,
x1+radius, y1,
x2-radius, y1,
x2-radius, y1,
x2, y1,
x2, y1+radius,
x2, y1+radius,
x2, y2-radius,
x2, y2-radius,
x2, y2,
x2-radius, y2,
x2-radius, y2,
x1+radius, y2,
x1+radius, y2,
x1, y2,
x1, y2-radius,
x1, y2-radius,
x1, y1+radius,
x1, y1+radius,
x1, y1]
if not update:
return self.create_polygon(points, **kwargs, smooth=True)
else:
self.coords(self.rect, points)
def resize(self, event):
text_bbox = self.bbox(self.text)
if self.radius > event.width or self.radius > event.height:
radius = min((event.width, event.height))
else:
radius = self.radius
width, height = event.width, event.height
if event.width < text_bbox[2]-text_bbox[0]:
width = text_bbox[2]-text_bbox[0] + 30
if event.height < text_bbox[3]-text_bbox[1]:
height = text_bbox[3]-text_bbox[1] + 30
self.round_rectangle(5, 5, width-5, height-5, radius, update=True)
bbox = self.bbox(self.rect)
x = ((bbox[2]-bbox[0])/2) - ((text_bbox[2]-text_bbox[0])/2)
y = ((bbox[3]-bbox[1])/2) - ((text_bbox[3]-text_bbox[1])/2)
self.moveto(self.text, x, y)
def border(self, event):
if event.type == "4":
self.itemconfig(self.rect, fill="#d2d6d3")
if self.clicked is not None:
self.clicked()
else:
self.itemconfig(self.rect, fill=self.btnbackground)
def func():
print("Button pressed")
root = tk.Tk()
btn = RoundedButton(text="This is a \n rounded button", radius=100, btnbackground="#0078ff", btnforeground="#ffffff", clicked=func)
btn.pack(expand=True, fill="both")
root.mainloop()
使用
canvas.create_rectangle()
和
canvas.create_text()
方法创建按钮,并将它们都分配给相同的标签,如
"button"
。在使用
canvas.tag_bind("tag", "<ButtonPress>")
时,将使用该标签(您还可以简单地传递标记为
"current"
,此时标记分配给tkinter选择的项目,在这种情况下,您可以删除按钮标记)。
请在画布元素上使用
canvas.tag_bind
而不是在画布上使用
bind
,这样鼠标按下事件仅在圆形按钮内部发生时更改按钮颜色,而不是在边缘发生时更改。
您可以扩展并改进此功能,以在单击按钮内部时生成自定义事件,添加配置方法以配置按钮文本和背景等。
输出: