Tkinter 中的交互式和漂亮的按钮
Interactive and nice looking buttons in Tkinter
我目前正在探索 Tkinter,我有一个关于按钮 GUI 的问题。我正在寻找创建一个干净简单的平面按钮。我通过互联网(主要是其他 Whosebug 问题)发现,这是可以通过创建图像按钮来实现的。但是,有什么方法可以通过在用户将鼠标悬停在按钮上时更改图像或在单击时更改图像来使这些按钮更具交互性?
提前感谢任何回答的人!
要让按钮在悬停时改变颜色,您可以试试下面的代码。但是,如果您希望界面看起来漂亮,我不建议使用 Tkinter。如果可以,试试 Kivy。它真的有助于制作自然的用户界面!
无论如何,这是在悬停时改变颜色的按钮的代码:
from tkinter import ttk
import tkinter as tk
# Create a window
root = tk.Tk()
root.geometry("500x500")
# Create style Object
style = ttk.Style()
style.configure("TButton", font=("Calibri", 20, "bold"), borderwidth=4)
# Changes will be reflected
# by the movement of mouse.
style.map("TButton", foreground=[("active", "disabled", "green")],
background=[("active", "black")])
# Button 1
btn1 = ttk.Button(root, text="Quit!", command=root.destroy)
btn1.grid(row=0, column=3, padx=100)
# Button 2
btn2 = ttk.Button(root, text="Click me!")
btn2.grid(row=1, column=3, pady=10, padx=100)
# Start tkinter's main loop
root.mainloop()
这个怎么样?使用 bind
会有帮助。
from tkinter import *
class InterActiveButton:
def __init__(self,root):
self.root = root
self.root.geometry("800x600")
self.button1=Button(self.root,bg="dark blue",fg="#dad122",cursor="hand2",text="Button 1",font=("arial",18,"bold"),bd=0,activebackground="dark blue",activeforeground="#dad122")
self.button1.place(x=10,y=10,width=200,height=50)
self.button1.bind("<Enter>",self.on_hover)
self.button1.bind("<Leave>",self.on_leave)
self.button3=Button(self.root,bg="dark blue",fg="#dad122",cursor="hand2",text="Button 2",font=("arial",18,"bold"),bd=0,activebackground="dark blue",activeforeground="#dad122")
self.button3.place(x=230,y=10,width=200,height=50)
self.button3.bind("<Enter>",self.on_hover)
self.button3.bind("<Leave>",self.on_leave)
self.button3=Button(self.root,bg="dark blue",fg="#dad122",cursor="hand2",text="Button 3",font=("arial",18,"bold"),bd=0,activebackground="dark blue",activeforeground="#dad122")
self.button3.place(x=450,y=10,width=200,height=50)
self.button3.bind("<Enter>",self.on_hover)
self.button3.bind("<Leave>",self.on_leave)
def increase_width(self,ev):
if self.done!=12:
ev.place_configure(width=200+self.done)
self.width_b=200+self.done
print(self.width_b)
self.done+=1
self.root.after(5,lambda:self.increase_width(ev))
def decrease_width(self,ev):
if self.done!=12:
ev.place_configure(width=self.width_b-1)
self.width_b=self.width_b-1
print("-------------")
print(self.width_b)
self.done+=1
self.root.after(5,lambda:self.decrease_width(ev))
def on_hover(self,event,*args):
self.done=0
event.widget['bg']="#dad122"
event.widget['fg']="dark blue"
#event.widget.place_configure(width=210,height=55)
self.root.after(5,lambda: self.increase_width(event.widget))
def on_leave(self,event,*args):
self.done=0
event.widget['fg']="#dad122"
event.widget['bg']="dark blue"
#event.widget.place_configure(width=200,height=50)
self.root.after(5,lambda: self.decrease_width(event.widget))
root=Tk()
ob=InterActiveButton(root)
root.mainloop()
@TheLizzard 编辑:
如果您希望能够将它与任何几何管理器一起使用,请使用:
import tkinter as tk
class InterActiveButton(tk.Button):
"""
This button expands when the user hovers over it and shrinks when
the cursor leaves the button.
If you want the button to expand in both directions just use:
button = InterActiveButton(root, text="Button", width=200, height=50)
button.pack()
If you want the button to only expand to the right use:
button = InterActiveButton(root, text="Button", width=200, height=50)
button.pack(anchor="w")
This button should work with all geometry managers.
"""
def __init__(self, master, max_expansion:int=12, bg="dark blue",
fg="#dad122", **kwargs):
# Save some variables for later:
self.max_expansion = max_expansion
self.bg = bg
self.fg = fg
# To use the button's width in pixels:
# From here:
self.pixel = tk.PhotoImage(width=1, height=1)
# The default button arguments:
button_args = dict(cursor="hand2", bd=0, font=("arial", 18, "bold"),
height=50, compound="c", activebackground=bg,
image=self.pixel, activeforeground=fg)
button_args.update(kwargs)
super().__init__(master, bg=bg, fg=fg, **button_args)
# Bind to the cursor entering and exiting the button:
super().bind("<Enter>", self.on_hover)
super().bind("<Leave>", self.on_leave)
# Save some variables for later:
self.base_width = button_args.pop("width", 200)
self.width = self.base_width
# `self.mode` can be "increasing"/"decreasing"/None only
# It stops a bug where if the user wuickly hovers over the button
# the button doesn't go back to normal
self.mode = None
def increase_width(self) -> None:
if self.width <= self.base_width + self.max_expansion:
if self.mode == "increasing":
self.width += 1
super().config(width=self.width)
super().after(5, self.increase_width)
def decrease_width(self) -> None:
if self.width > self.base_width:
if self.mode == "decreasing":
self.width -= 1
super().config(width=self.width)
super().after(5, self.decrease_width)
def on_hover(self, event:tk.Event=None) -> None:
# Improvement: use integers instead of "increasing" and "decreasing"
self.mode = "increasing"
# Swap the `bg` and the `fg` of the button
super().config(bg=self.fg, fg=self.bg)
super().after(5, self.increase_width)
def on_leave(self, event:tk.Event=None) -> None:
# Improvement: use integers instead of "increasing" and "decreasing"
self.mode = "decreasing"
# Reset the `fg` and `bg` of the button
super().config(bg=self.bg, fg=self.fg)
super().after(5, self.decrease_width)
root = tk.Tk()
root.geometry("400x400")
button = InterActiveButton(root, text="Button", width=200, height=50)
# Using `anchor="w"` forces the button to expand to the right.
# If it's removed, the button will expand in both directions
button.pack(padx=20, pady=20, anchor="w")
root.mainloop()
这也解决了如果用户快速将鼠标悬停在按钮上时按钮不会恢复正常的问题。
我目前正在探索 Tkinter,我有一个关于按钮 GUI 的问题。我正在寻找创建一个干净简单的平面按钮。我通过互联网(主要是其他 Whosebug 问题)发现,这是可以通过创建图像按钮来实现的。但是,有什么方法可以通过在用户将鼠标悬停在按钮上时更改图像或在单击时更改图像来使这些按钮更具交互性?
提前感谢任何回答的人!
要让按钮在悬停时改变颜色,您可以试试下面的代码。但是,如果您希望界面看起来漂亮,我不建议使用 Tkinter。如果可以,试试 Kivy。它真的有助于制作自然的用户界面! 无论如何,这是在悬停时改变颜色的按钮的代码:
from tkinter import ttk
import tkinter as tk
# Create a window
root = tk.Tk()
root.geometry("500x500")
# Create style Object
style = ttk.Style()
style.configure("TButton", font=("Calibri", 20, "bold"), borderwidth=4)
# Changes will be reflected
# by the movement of mouse.
style.map("TButton", foreground=[("active", "disabled", "green")],
background=[("active", "black")])
# Button 1
btn1 = ttk.Button(root, text="Quit!", command=root.destroy)
btn1.grid(row=0, column=3, padx=100)
# Button 2
btn2 = ttk.Button(root, text="Click me!")
btn2.grid(row=1, column=3, pady=10, padx=100)
# Start tkinter's main loop
root.mainloop()
这个怎么样?使用 bind
会有帮助。
from tkinter import *
class InterActiveButton:
def __init__(self,root):
self.root = root
self.root.geometry("800x600")
self.button1=Button(self.root,bg="dark blue",fg="#dad122",cursor="hand2",text="Button 1",font=("arial",18,"bold"),bd=0,activebackground="dark blue",activeforeground="#dad122")
self.button1.place(x=10,y=10,width=200,height=50)
self.button1.bind("<Enter>",self.on_hover)
self.button1.bind("<Leave>",self.on_leave)
self.button3=Button(self.root,bg="dark blue",fg="#dad122",cursor="hand2",text="Button 2",font=("arial",18,"bold"),bd=0,activebackground="dark blue",activeforeground="#dad122")
self.button3.place(x=230,y=10,width=200,height=50)
self.button3.bind("<Enter>",self.on_hover)
self.button3.bind("<Leave>",self.on_leave)
self.button3=Button(self.root,bg="dark blue",fg="#dad122",cursor="hand2",text="Button 3",font=("arial",18,"bold"),bd=0,activebackground="dark blue",activeforeground="#dad122")
self.button3.place(x=450,y=10,width=200,height=50)
self.button3.bind("<Enter>",self.on_hover)
self.button3.bind("<Leave>",self.on_leave)
def increase_width(self,ev):
if self.done!=12:
ev.place_configure(width=200+self.done)
self.width_b=200+self.done
print(self.width_b)
self.done+=1
self.root.after(5,lambda:self.increase_width(ev))
def decrease_width(self,ev):
if self.done!=12:
ev.place_configure(width=self.width_b-1)
self.width_b=self.width_b-1
print("-------------")
print(self.width_b)
self.done+=1
self.root.after(5,lambda:self.decrease_width(ev))
def on_hover(self,event,*args):
self.done=0
event.widget['bg']="#dad122"
event.widget['fg']="dark blue"
#event.widget.place_configure(width=210,height=55)
self.root.after(5,lambda: self.increase_width(event.widget))
def on_leave(self,event,*args):
self.done=0
event.widget['fg']="#dad122"
event.widget['bg']="dark blue"
#event.widget.place_configure(width=200,height=50)
self.root.after(5,lambda: self.decrease_width(event.widget))
root=Tk()
ob=InterActiveButton(root)
root.mainloop()
@TheLizzard 编辑:
如果您希望能够将它与任何几何管理器一起使用,请使用:
import tkinter as tk
class InterActiveButton(tk.Button):
"""
This button expands when the user hovers over it and shrinks when
the cursor leaves the button.
If you want the button to expand in both directions just use:
button = InterActiveButton(root, text="Button", width=200, height=50)
button.pack()
If you want the button to only expand to the right use:
button = InterActiveButton(root, text="Button", width=200, height=50)
button.pack(anchor="w")
This button should work with all geometry managers.
"""
def __init__(self, master, max_expansion:int=12, bg="dark blue",
fg="#dad122", **kwargs):
# Save some variables for later:
self.max_expansion = max_expansion
self.bg = bg
self.fg = fg
# To use the button's width in pixels:
# From here:
self.pixel = tk.PhotoImage(width=1, height=1)
# The default button arguments:
button_args = dict(cursor="hand2", bd=0, font=("arial", 18, "bold"),
height=50, compound="c", activebackground=bg,
image=self.pixel, activeforeground=fg)
button_args.update(kwargs)
super().__init__(master, bg=bg, fg=fg, **button_args)
# Bind to the cursor entering and exiting the button:
super().bind("<Enter>", self.on_hover)
super().bind("<Leave>", self.on_leave)
# Save some variables for later:
self.base_width = button_args.pop("width", 200)
self.width = self.base_width
# `self.mode` can be "increasing"/"decreasing"/None only
# It stops a bug where if the user wuickly hovers over the button
# the button doesn't go back to normal
self.mode = None
def increase_width(self) -> None:
if self.width <= self.base_width + self.max_expansion:
if self.mode == "increasing":
self.width += 1
super().config(width=self.width)
super().after(5, self.increase_width)
def decrease_width(self) -> None:
if self.width > self.base_width:
if self.mode == "decreasing":
self.width -= 1
super().config(width=self.width)
super().after(5, self.decrease_width)
def on_hover(self, event:tk.Event=None) -> None:
# Improvement: use integers instead of "increasing" and "decreasing"
self.mode = "increasing"
# Swap the `bg` and the `fg` of the button
super().config(bg=self.fg, fg=self.bg)
super().after(5, self.increase_width)
def on_leave(self, event:tk.Event=None) -> None:
# Improvement: use integers instead of "increasing" and "decreasing"
self.mode = "decreasing"
# Reset the `fg` and `bg` of the button
super().config(bg=self.bg, fg=self.fg)
super().after(5, self.decrease_width)
root = tk.Tk()
root.geometry("400x400")
button = InterActiveButton(root, text="Button", width=200, height=50)
# Using `anchor="w"` forces the button to expand to the right.
# If it's removed, the button will expand in both directions
button.pack(padx=20, pady=20, anchor="w")
root.mainloop()
这也解决了如果用户快速将鼠标悬停在按钮上时按钮不会恢复正常的问题。