Python Button With Background Image

How to Create Custom Image Buttons in Python Tkinter

How to Create Custom Image Buttons in Python Tkinter


In this Python Tutorial we will see How to Create a Custom Image Button class that transforms any image into an interactive button with Hover effects, Press effects, Text overlays and Fallback gradient.

What We Are Gonna Use In This Project:

- Python Programming Language.
- Tkinter (GUI).
- VS Editor.






Project Source Code:





import tkinter as tk
from tkinter import messagebox
from PIL import Image, ImageTk, ImageEnhance
import os

# Set working directory to the script's location
os.chdir(os.path.dirname(os.path.abspath(__file__)))

class CustomImageButton(tk.Canvas):
"""Canvas-based button with image background and text overlay"""

def __init__(self, parent, image_path, text, command=None, width=200, height=60):
# Initialize canvas with specified dimensions and no border
super().__init__(
parent,
width=width,
height=height,
highlightthickness=0
)
self.command = command
self.width = width
self.height = height

# Load and prepare button images for different states
try:
# Load and resize the base image
self.original_image = Image.open(image_path)
self.original_image = self.original_image.resize((width, height),
Image.LANCZOS)
self.normal_image = ImageTk.PhotoImage(self.original_image)

# Create brighter version for hover state (20% brighter)
brightener = ImageEnhance.Brightness(self.original_image)
bright_image = brightener.enhance(1.2)
self.hover_image = ImageTk.PhotoImage(bright_image)

# Create darker version for pressed state (20% darker)
darkener = ImageEnhance.Brightness(self.original_image)
dark_image = darkener.enhance(0.8)
self.pressed_image = ImageTk.PhotoImage(dark_image)

except Exception as e:
print(f"Error loading image: {e}")
# Fall back to gradient if image can't be loaded
self.create_gradient_background()

# Add background image to the canvas
self.normal_bg = self.create_image(0, 0, anchor='nw', image=self.normal_image)

# Add main text centered on the button
self.text_item = self.create_text(
width // 2,
height // 2,
text=text,
fill='black',
font=('Arial', 12, 'bold')
)

# Add a yellow text (on top of the main text) for better readability
# (offset by 1 pixel)
self.create_text(
width // 2 + 1,
height // 2 + 1,
text=text,
fill='yellow',
font=('Arial', 12, 'bold')
)

# Configure mouse event handlers
self.bind('<Enter>', self.on_enter) # Mouse enters button area
self.bind('<Leave>', self.on_leave) # Mouse exits button area
self.bind('<Button-1>', self.on_press) # Mouse button pressed down
self.bind('<ButtonRelease-1>', self.on_release) # Mouse button released

def create_gradient_background(self):
"""Create fallback gradient images if the main image fails to load"""
# Generate a blue gradient from top to bottom
gradient = Image.new('RGB', (self.width, self.height))
for y in range(self.height):
# Calculate color for this row (gradient from blue to lighter blue)
r = int(64 + (14 - 64) * y / self.height)
g = int(134 + (82 - 134) * y / self.height)
b = int(244 + (194 - 244) * y / self.height)

# Apply the color to each pixel in this row
for x in range(self.width):
gradient.putpixel((x, y), (r, g, b))

# Create versions for each button state
self.normal_image = ImageTk.PhotoImage(gradient)
brightener = ImageEnhance.Brightness(gradient)
self.hover_image = ImageTk.PhotoImage(brightener.enhance(1.2))
self.pressed_image = ImageTk.PhotoImage(brightener.enhance(0.8))


def on_enter(self, event):
"""Change to hover image when mouse enters button area"""
self.itemconfig(self.normal_bg, image=self.hover_image)
def on_leave(self, event):
"""Change back to normal image when mouse leaves button area"""
self.itemconfig(self.normal_bg, image=self.normal_image)
def on_press(self, event):
"""Change to pressed image when button is clicked"""
self.itemconfig(self.normal_bg, image=self.pressed_image)
def on_release(self, event):
"""Execute command when button is released and return to hover state"""
self.itemconfig(self.normal_bg, image=self.hover_image)
if self.command:
self.command()


class App(tk.Tk):
"""Main application window"""

def __init__(self):
# Initialize the main window
super().__init__()

self.title("Custom Image Button")
self.geometry("400x300")

# Center the window on screen
screen_width = self.winfo_screenwidth()
screen_height = self.winfo_screenheight()
x = (screen_width - 400) // 2
y = (screen_height - 300) // 2
self.geometry(f"400x300+{x}+{y}")

# Create and add a custom image button
button = CustomImageButton(
self,
"images/coffee-3936903_640.jpg", # Image path (should be in images folder)
"Click Me",
command=self.button_click
)
button.pack(pady=50) # Add button with vertical padding
def button_click(self):
"""Display a message when button is clicked"""
messagebox.showinfo("Click", "Button clicked!")

if __name__ == "__main__":
# Create and run the application
app = App()
app.mainloop()





The Final Result:











Aucun commentaire:

Enregistrer un commentaire