OmerC
OmerC

Reputation: 29

Image in Button tkinter

I am having a problem in making a login image to a button. I have succeeded in making the image with a transparent background, but I can't succeed to make the button with transparent background.

I attached a screenshot that shows what I mean. The upper 'login' is a image (with transparent background), the lower is Login button but there is a white background around it. I want to make a button with transparent background.

self.login_image = Image.open('images/LoginButton.png')
self.login_image = ImageTk.PhotoImage(self.login_image)
self.main_screen_canvas.create_image(700, 300, image=self.login_image)

self.login_button = Button(self.main_screen_canvas, borderwidth=0, image=self.login_image)

self.login_button.place(x=300,y=400)

What should I do?

enter image description here

BackgroundImage LoginButtonImage

Upvotes: 0

Views: 1055

Answers (1)

martineau
martineau

Reputation: 123463

Here's how to do what I was suggesting in the comment which uses the technique shown in another answer of mine to simulate a tkinter Button on a Canvas that has a transparent image placed on it (instead of text).

One issue I ran into was that fact that your 2421 × 1210 pixel background image was larger than my screen. To deal with it I added a fitrect() helper function to determine a new smaller size for it that would fit. I wrote it a long time ago, but have found it handy to have around many times (like now). Note that in the code ll and ur refer to the lower-left and upper-right corners of the rectangles involved.

Here's the resulting code:

from PIL import Image, ImageTk
import tkinter as tk

class CanvasButton:
    """ Create left mouse button clickable canvas image object.

    The x, y coordinates are relative to the top-left corner of the canvas.
    """
    flash_delay = 100  # Milliseconds.

    def __init__(self, canvas, x, y, image_source, command, state=tk.NORMAL):
        self.canvas = canvas

        if isinstance(image_source, str):
            self.btn_image = tk.PhotoImage(file=image_source)
        else:
            self.btn_image = image_source

        self.canvas_btn_img_obj = canvas.create_image(x, y, anchor='nw', state=state,
                                                      image=self.btn_image)
        canvas.tag_bind(self.canvas_btn_img_obj, "<ButtonRelease-1>",
                        lambda event: (self.flash(), command()))

    def flash(self):
        self.set_state(tk.HIDDEN)
        self.canvas.after(self.flash_delay, self.set_state, tk.NORMAL)

    def set_state(self, state):
        """ Change canvas button image's state.

        Normally, image objects are created in state tk.NORMAL. Use value
        tk.DISABLED to make it unresponsive to the mouse, or use tk.HIDDEN to
        make it invisible.
        """
        self.canvas.itemconfigure(self.canvas_btn_img_obj, state=state)


def fitrect(r1_ll_x, r1_ll_y, r1_ur_x, r1_ur_y, r2_ll_x, r2_ll_y, r2_ur_x, r2_ur_y):
    """ Find the largest rectangle that will fit within rectangle r2 that has
        rectangle r1's aspect ratio.

        Note: Either the width or height of the resulting rect will be
              identical to the corresponding dimension of rect r2.
    """
    # Calculate aspect ratios of rects r1 and r2.
    deltax1, deltay1 = (r1_ur_x - r1_ll_x), (r1_ur_y - r1_ll_y)
    deltax2, deltay2 = (r2_ur_x - r2_ll_x), (r2_ur_y - r2_ll_y)
    aspect1, aspect2 = (deltay1 / deltax1), (deltay2 / deltax2)

    # Compute size of resulting rect depending on which aspect ratio is bigger.
    if aspect1 > aspect2:
        result_ll_y, result_ur_y = r2_ll_y, r2_ur_y
        delta = deltay2 / aspect1
        result_ll_x = r2_ll_x + (deltax2 - delta) / 2.0
        result_ur_x = result_ll_x + delta
    else:
        result_ll_x, result_ur_x = r2_ll_x, r2_ur_x
        delta = deltax2 * aspect1
        result_ll_y = r2_ll_y + (deltay2 - delta) / 2.0
        result_ur_y = result_ll_y + delta

    return result_ll_x, result_ll_y, result_ur_x, result_ur_y

def btn_clicked():
    """ Prints to console a message every time the button is clicked """
    print("Button Clicked")


background_image_path = 'background_image.jpg'
button_image_path = 'button_image.png'

root = tk.Tk()
root.update_idletasks()
background_img = Image.open(background_image_path)  # Must use PIL for JPG images.

scrnwidth, scrnheight = root.winfo_screenwidth(), root.winfo_screenheight()
bgrdwidth, bgrdheight = background_img.size
border_width, border_height = 20, 20  # Allow room for window's decorations.

# Determine a background image size that will fit on screen with a border.
bgr_ll_x, bgr_ll_y, bgr_ur_x, bgr_ur_y = fitrect(
                                0, 0, bgrdwidth, bgrdheight,
                                0, 0, scrnwidth-border_width, scrnheight-border_height)
bgr_width, bgr_height = int(bgr_ur_x-bgr_ll_x), int(bgr_ur_y-bgr_ll_y)

# Resize background image to calculated size.
background_img = ImageTk.PhotoImage(background_img.resize((bgr_width, bgr_height)))

# Create Canvas same size as fitted background image.
canvas = tk.Canvas(root, bd=0, highlightthickness=0, width=bgr_width, height=bgr_height)
canvas.pack(fill=tk.BOTH)

# Put background image on Canvas.
background = canvas.create_image(0, 0, anchor='nw', image=background_img)

# Put CanvasButton on Canvas centered at the bottom.
button_img = tk.PhotoImage(file=button_image_path)
btn_x, btn_y = (bgr_width/2), (bgr_height-button_img.height())

canvas_btn1 = CanvasButton(canvas, btn_x, btn_y, button_img, btn_clicked)

root.mainloop()

And here's the result of running it:

screenshot of background image with a button on it with a transparent background

Upvotes: 1

Related Questions