Mar*_*fse 6 python tkinter tkinter-canvas
我正在尝试使用tkinter为我的脚本获取圆形按钮。
我发现以下代码:
from tkinter import *
import tkinter as tk
class CustomButton(tk.Canvas):
def __init__(self, parent, width, height, color, command=None):
tk.Canvas.__init__(self, parent, borderwidth=1,
relief="raised", highlightthickness=0)
self.command = command
padding = 4
id = self.create_oval((padding,padding,
width+padding, height+padding), outline=color, fill=color)
(x0,y0,x1,y1) = self.bbox("all")
width = (x1-x0) + padding
height = (y1-y0) + padding
self.configure(width=width, height=height)
self.bind("<ButtonPress-1>", self._on_press)
self.bind("<ButtonRelease-1>", self._on_release)
def _on_press(self, event):
self.configure(relief="sunken")
def _on_release(self, event):
self.configure(relief="raised")
if self.command is not None:
self.command()
app = CustomButton()
app.mainloop()
Run Code Online (Sandbox Code Playgroud)
但我收到以下错误:
TypeError: __init__() missing 4 required positional arguments: 'parent', 'width', 'height', and 'color'
Run Code Online (Sandbox Code Playgroud)
Gua*_*uac 10
如果有人正在寻找更多苹果外观或其他东西,我制作了这个圆角矩形按钮。为方便起见,这里是参数:
RoundedButton(parent, width, height, cornerradius, padding, fillcolor, background, command)
Run Code Online (Sandbox Code Playgroud)
注意:如果拐角半径大于宽度或高度的一半,终端将发送错误消息。如果您将拐角半径设置为高度或宽度的一半,则仍然可以制作药丸形状。
最后是代码:
from tkinter import *
import tkinter as tk
root = Tk()
class RoundedButton(tk.Canvas):
def __init__(self, parent, width, height, cornerradius, padding, color, bg, command=None):
tk.Canvas.__init__(self, parent, borderwidth=0,
relief="flat", highlightthickness=0, bg=bg)
self.command = command
if cornerradius > 0.5*width:
print("Error: cornerradius is greater than width.")
return None
if cornerradius > 0.5*height:
print("Error: cornerradius is greater than height.")
return None
rad = 2*cornerradius
def shape():
self.create_polygon((padding,height-cornerradius-padding,padding,cornerradius+padding,padding+cornerradius,padding,width-padding-cornerradius,padding,width-padding,cornerradius+padding,width-padding,height-cornerradius-padding,width-padding-cornerradius,height-padding,padding+cornerradius,height-padding), fill=color, outline=color)
self.create_arc((padding,padding+rad,padding+rad,padding), start=90, extent=90, fill=color, outline=color)
self.create_arc((width-padding-rad,padding,width-padding,padding+rad), start=0, extent=90, fill=color, outline=color)
self.create_arc((width-padding,height-rad-padding,width-padding-rad,height-padding), start=270, extent=90, fill=color, outline=color)
self.create_arc((padding,height-padding-rad,padding+rad,height-padding), start=180, extent=90, fill=color, outline=color)
id = shape()
(x0,y0,x1,y1) = self.bbox("all")
width = (x1-x0)
height = (y1-y0)
self.configure(width=width, height=height)
self.bind("<ButtonPress-1>", self._on_press)
self.bind("<ButtonRelease-1>", self._on_release)
def _on_press(self, event):
self.configure(relief="sunken")
def _on_release(self, event):
self.configure(relief="raised")
if self.command is not None:
self.command()
def test():
print("Hello")
canvas = Canvas(root, height=300, width=500)
canvas.pack()
button = RoundedButton(root, 200, 100, 50, 2, 'red', 'white', command=test)
button.place(relx=.1, rely=.1)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)
在tkinter中制作圆形按钮的一种非常简单的方法是使用图像。
首先创建一个图像,使您想要的按钮看起来像是将其另存为.png并删除外部背景,以便将其四舍五入,如下所示:

接下来,将图像插入按钮,PhotoImage如下所示:
self.loadimage = tk.PhotoImage(file="rounded_button.png")
self.roundedbutton = tk.Button(self, image=self.loadimage)
self.roundedbutton["bg"] = "white"
self.roundedbutton["border"] = "0"
self.roundedbutton.pack(side="top")
Run Code Online (Sandbox Code Playgroud)
确保使用border="0",并且按钮边框将被移除。
我添加了,self.roundedborder["bg"] = "white"以便按钮的背景与Tkinter窗口的背景相同。
最重要的是,您可以使用任何喜欢的形状,而不仅仅是普通的按钮形状。
不幸的是,调整大小后图像效果不佳。
下面是使用画布的圆形按钮的示例,即使调整大小也能正常工作。
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): # if update is False a new rounded rectangle's id will be returned else updates existing rounded rect.
# source: https://stackoverflow.com/a/44100075/15993687
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()
Run Code Online (Sandbox Code Playgroud)
要创建此用途canvas.create_rectangle()和canvas.create_text()方法,并给它们提供相同的标签,例如"button". 使用时会用到该标签canvas.tag_bind("tag", "<ButtonPress>")(你也可以简单地传递"current"为标签,它由 tkinter 分配给当前选定的项目,在这种情况下你可以删除按钮标签)。
在画布项目上使用canvas.tag_bind而不是bind在画布上使用,这样,只有当鼠标按下发生在圆形按钮内部而不是边缘时,按钮颜色才会改变。
您可以扩展和改进它,以便在按钮内部单击时生成自定义事件,添加配置方法来配置按钮文本和背景等。
您没有将任何参数传递给构造函数。
具体来说,在这条线上
app = CustomButton()
Run Code Online (Sandbox Code Playgroud)
你需要通过在构造函数中定义,即中定义的参数parent,width,height和color。
您需要首先创建根窗口(或其他一些小部件)并将其CustomButton与不同的参数一起提供给您(参见__init__方法的定义)。
尝试而不是app = CustomButton()以下内容:
app = tk.Tk()
button = CustomButton(app, 100, 25, 'red')
button.pack()
app.mainloop()
Run Code Online (Sandbox Code Playgroud)