Day3的时候我们使用Tkinter的组件button创建了按钮,但是这个按钮局限性很大:
- 边框问题:即使设置borderwidth=0, highlightthickness=0, relief="flat"(无边框、无高亮点击、按钮平整),但是当我们点击按钮时还是会出现边框,影响美观。
- 背景问题:我们虽然可以任意改变按钮的填充颜色,但是几乎无法直接做到按钮透明。即使设置按钮与背景颜色一致,但是还是会受其他组件的影响。
解决方案:
- 使用Label组件制作文字或图片按钮。这可以有效避免按钮边框问题,并且使用图片可以大幅增加按钮外观的美感。但是使用文字时还是有文字背景的局限性。
- 使用canvas组件绘制,这个解决办法几乎完美。无论是边框还是背景,甚至是按钮形状,都可以达到让人满意的程度。
1. Label_Button
设计思想:使用两张图片作为按钮背景,一张亮,一张暗(初始化),当鼠标移动至按钮上方时,按钮由暗变亮,离开时又变回暗色。
def label_button(root):
# 加载图片
dark_image = tk.PhotoImage(file="images\CloseButton.png") # 替换为你的暗图片路径
light_image = tk.PhotoImage(file="images\CloseButtonHighlight.png") # 替换为你的亮图片路径
def on_enter(event):
"""鼠标进入Label时调用的函数"""
label.config(image=light_image)
def on_leave(event):
"""鼠标离开Label时调用的函数"""
label.config(image=dark_image)
def on_click(event):
"""Label被点击时调用的函数"""
messagebox.showinfo("点击了!", "按钮被点击了")
# 创建Label作为按钮
label = tk.Label(root, image=dark_image, cursor="hand2",bg='lightBlue')
label.pack(pady=20)
# 绑定鼠标事件
label.bind("<Enter>", on_enter)
label.bind("<Leave>", on_leave)
label.bind("<Button-1>", on_click) # 绑定鼠标左键点击事件
效果:
由于图片是有透明通道的,当图片背景与窗口背景颜色设置为同一颜色,那么效果就相当出色,否则就会:
还有一个小技巧,如果插入的图片是矩形,那么可以设置bd=0使得按钮始终无边框。
但是请注意,一个label不能同时加载图片和文本,如果需要同时的话,需要创建两个label。
2. Canvas_button
Tkinter 的 Canvas
是一个用于在窗口中绘制图形和图像的组件。它允许用户在窗口中添加矩形、圆形、线条、文本和位图等元素。
设计思路:canvas的功能真的很强大,首先我们可以创建一个画布铺满屏幕,然后随意填充图片作为背景,当我们需要按钮时,我们可以使用基础的button,或上述的label_button,甚至可以自己绘制图形作为按钮。重点在于
绘制图形的这三个参数:
- width:边框宽度
- outline:边框颜色
- fill:填充颜色
以及事件函数定义:
def on_button_click(event):
tk.messagebox.showinfo("按钮点击", "按钮被点击了")
def on_hover(event):
canvas.itemconfig(label, fill="white")
canvas.itemconfig(button, fill="black")
canvas.update_idletasks()
def on_leave(event):
canvas.itemconfig(label, fill="black")
canvas.itemconfig(button, fill="white")
canvas.update_idletasks()
下面这段代码中,我们绘制了一个矩形作为按钮,矩形内部创建了一个文本。
def canvas_button(root,width,height):
def on_button_click(event):
tk.messagebox.showinfo("按钮点击", "按钮被点击了")
def on_hover(event):
canvas.itemconfig(label, fill="white")
canvas.itemconfig(button, fill="black")
canvas.update_idletasks()
def on_leave(event):
canvas.itemconfig(label, fill="black")
canvas.itemconfig(button, fill="white")
canvas.update_idletasks()
# 创建画布
canvas = tk.Canvas(root, width=width, height=height, bg="white",bd=0)
canvas.pack()
# 加载图片
img = Image.open("images\Almanac_ZombieBack.jpg")
img = img.resize((width, height), Image.Resampling.LANCZOS)
photo = ImageTk.PhotoImage(img)
canvas.create_image(width//2, height//2, image=photo)
canvas.photo = photo
# 创建透明按钮
button_width = 100
button_height = 50
button_x = 390
button_y = 500
# 创建按钮,设置透明背景和文字
# 按钮可以为任意形状,只要设置width为0,不填充颜色,就可以做到透明
button = canvas.create_rectangle(button_x, button_y, button_x + button_width, button_y + button_height,
width=1,
outline="red",
fill="white"
)
label = canvas.create_text(button_x + button_width // 2,
button_y + button_height // 2,
text="点击我", fill="black", font=("Arial", 16))
# 鼠标悬停和离开事件处理
canvas.tag_bind(label, "<Enter>", on_hover)
canvas.tag_bind(button, "<Enter>", on_hover)
canvas.tag_bind(label, "<Leave>", on_leave)
canvas.tag_bind(button, "<Leave>", on_leave)
# 点击按钮事件处理
canvas.tag_bind(button, "<Button-1>", on_button_click)
canvas.tag_bind(label, "<Button-1>", on_button_click)
结果1:
- width=1,
- outline="red",
- fill="white"
这个按钮和普通button非常相似,拥有红色外框,未被点击或鼠标置于上方时,是白色背景黑色字体,当鼠标在上方浮动时变为黑色背景白色字体。
结果2:
- width=0,
- # outline="red"
- # fill="white"
- 注释掉事件处理函数中对填充颜色的修改
结果三:
- width=1,
- outline="black"
- # fill="white"
- 注释掉事件处理函数中对填充颜色的修改
我们可以看出,在使用canvas制作普通按钮时,我们可以对边框颜色、填充颜色、字体颜色进行单独设置,若需要进一步美化,只需绘制更精美的按钮形状或是使用图片作为按钮背景。举个圆角矩形框的例子:
def draw_rounded_rectangle(canvas, x, y, width, height, radius):
# 绘制左上角的弧形
canvas.create_oval(x, y, x + radius, y + radius, width=0, fill='white')
# 绘制右上角的弧形
canvas.create_oval(x + width - radius, y, x + width, y + radius, width=0, fill='white')
# 绘制右下角的弧形
canvas.create_oval(x + width - radius, y + height - radius, x + width, y + height, width=0, fill='white')
# 绘制左下角的弧形
canvas.create_oval(x, y + height - radius, x + radius, y + height, width=0, fill='white')
# 绘制矩形的主体
canvas.create_rectangle(x + radius, y + radius, x + width - radius, y + height - radius, width=2, outline='black')
3. 总结
今天使用label和canvas制作更精美的按钮,具有非常高的可创造性,可以大幅提升界面美感。源码:
import tkinter as tk
from PIL import Image, ImageTk
from Day2 import *
def label_button(root):
# 加载图片
dark_image = tk.PhotoImage(file="images\CloseButton.png") # 替换为你的暗图片路径
light_image = tk.PhotoImage(file="images\CloseButtonHighlight.png") # 替换为你的亮图片路径
def on_enter(event):
"""鼠标进入Label时调用的函数"""
label.config(image=light_image)
def on_leave(event):
"""鼠标离开Label时调用的函数"""
label.config(image=dark_image)
def on_click(event):
"""Label被点击时调用的函数"""
messagebox.showinfo("点击了!", "按钮被点击了")
# 创建Label作为按钮
label = tk.Label(root, image=dark_image, cursor="hand2",bg='Blue')
label.pack(pady=20)
# 绑定鼠标事件
label.bind("<Enter>", on_enter)
label.bind("<Leave>", on_leave)
label.bind("<Button-1>", on_click) # 绑定鼠标左键点击事件
def canvas_button(root,width,height):
def on_button_click(event):
tk.messagebox.showinfo("按钮点击", "按钮被点击了")
def on_hover(event):
canvas.itemconfig(label, fill="white")
canvas.itemconfig(button, fill="black")
canvas.update_idletasks()
def on_leave(event):
canvas.itemconfig(label, fill="black")
canvas.itemconfig(button, fill="white")
canvas.update_idletasks()
# 创建画布
canvas = tk.Canvas(root, width=width, height=height, bg="white",bd=0)
canvas.pack()
# 加载图片
img = Image.open("images\Almanac_ZombieBack.jpg")
img = img.resize((width, height), Image.Resampling.LANCZOS)
photo = ImageTk.PhotoImage(img)
canvas.create_image(width//2, height//2, image=photo)
canvas.photo = photo
# 创建透明按钮
button_width = 100
button_height = 50
button_x = 390
button_y = 500
# 创建按钮,设置透明背景和文字
# 按钮可以为任意形状,只要设置width为0,不填充颜色,就可以做到透明
button = canvas.create_rectangle(button_x, button_y, button_x + button_width, button_y + button_height,
width=1,
outline="red",
fill="white"
)
label = canvas.create_text(button_x + button_width // 2,
button_y + button_height // 2,
text="点击我", fill="black", font=("Arial", 16))
# 鼠标悬停和离开事件处理
canvas.tag_bind(label, "<Enter>", on_hover)
canvas.tag_bind(button, "<Enter>", on_hover)
canvas.tag_bind(label, "<Leave>", on_leave)
canvas.tag_bind(button, "<Leave>", on_leave)
# 点击按钮事件处理
canvas.tag_bind(button, "<Button-1>", on_button_click)
canvas.tag_bind(label, "<Button-1>", on_button_click)
if __name__=="__main__":
root = tk.Tk()
window_width = 880
window_height = 600
title_and_icon(root)
window_size(root,window_width,window_height)
window_location(root,window_width,window_height)
root.configure(bg='lightBlue') # 设置窗口背景颜色为红色
#label_button(root)
canvas_button(root,window_width,window_height)
root.mainloop()