Skip to content Skip to sidebar Skip to footer

Interactive And Nice Looking Buttons In Tkinter

I'm currently exploring Tkinter and I have a question about Button GUI. I'm looking to create a clean and simple flat button. I have discovered through the internet (mainly other S

Solution 1:

How about this? Using bind will help.

from tkinter import *
classInterActiveButton:
    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)
    defincrease_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))
    defdecrease_width(self,ev):
        if self.done!=12:
            ev.place_configure(width=self.width_b-1)
            self.width_b=self.width_b-1print("-------------")
            print(self.width_b)
            self.done+=1
            self.root.after(5,lambda:self.decrease_width(ev))
    defon_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))
    defon_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()

Edit by @TheLizzard:

If you want to be able to use it with any geometry manager, use this:

import tkinter as tk


classInterActiveButton(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: https://stackoverflow.com/a/46286221/11106801
        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 = Nonedefincrease_width(self) -> None:
        if self.width <= self.base_width + self.max_expansion:
            if self.mode == "increasing":
                self.width += 1super().config(width=self.width)
                super().after(5, self.increase_width)

    defdecrease_width(self) -> None:
        if self.width > self.base_width:
            if self.mode == "decreasing":
                self.width -= 1super().config(width=self.width)
                super().after(5, self.decrease_width)

    defon_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 buttonsuper().config(bg=self.fg, fg=self.bg)
        super().after(5, self.increase_width)

    defon_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 buttonsuper().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()

This also fixes the problem with the button not returning to normal if the user quickly hovers over the button.

Solution 2:

To make the button change color on hover, you can try the below code. However, I would not suggest using Tkinter if you want your interface to look beautiful. Try Kivy if you can. It really helps in making a natural user interface! Anyways, here's the code for the button to change color on hover:

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()

Post a Comment for "Interactive And Nice Looking Buttons In Tkinter"