TKinter button over transparent background
Asked Answered
H

1

0

I am trying to understand how to apply a button to a transparent background while keeping its shape. When I generate the code below, there is a gray background around the border that appears, and it also looks like it loses its shape.

Colors Used

Sidebar: #2E3A4B at 53%

Button: #2C2F33 at 100%

from tkinter import *


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


root = Tk()

# Configures the frame, and sets up the canvas
root.geometry("1440x1024")
root.configure(bg="#ffffff")
canvas = Canvas(root, bg="#ffffff", height=1024, width=1440, bd=0, highlightthickness=0, relief="ridge")
canvas.place(x=0, y=0)

background_img = PhotoImage(file=f"background.png")
background = canvas.create_image(719.5, 512.5, image=background_img)

img0 = PhotoImage(file=f"img0.png")
alarm_button = Button(image=img0, borderwidth=0, highlightthickness=0, command=btn_clicked, relief="flat")

alarm_button.place(x=9, y=119, width=90, height=90)

root.resizable(False, False)
root.mainloop()

Required Images

enter image description here enter image description here

How it looks:

enter image description here

How it should look:

enter image description here

Hieronymus answered 5/2, 2022 at 7:37 Comment(13)
No, I don't see it getting lighter.Superable
Thanks @Superable for pointing out it may have no been a good example image. I just retook one placing more buttons to show what I meant.Hieronymus
Sorry, they all look the same to me.Superable
No @martineau, it's my fault. I just updated the image with how It should look. If you notice with the problem image you can see the fixed colors behind it making the squares, then if you notice how it should look it is clean, and the buttons can be placed over the transparent issue no problem if this makes sense? The side bars color is: 2E3A4B with a transparency of 53%Hieronymus
What is the "other object of a fixed color" and where are you putting it behind the alarm button?Superable
I just updated everything above to be more clear @martineau, I realized the wording was confusing. I am just trying to figure out how to get the image to generate right. I have tried importing them as .gif but that didn't seem to work either.Hieronymus
OK, I now understand what you're asking and was able to reproduce the problem. Unfortunately I don't think you can do what you want with tkinter.Superable
That's the notion I was getting too @martineau, I ran across this post: #29858257 and it said there is a way, I just wasn't able to get it working because the code is a bit different, but still using Tkinter. Do you have any recommendations from viewing this?Hieronymus
Which answer to that linked question are you referring to?Superable
The last one @SuperableHieronymus
"last one" is meaningless since the order they get displayed in can vary. Either provide a link directly to the answer or specify the answer's author's user name.Superable
@Superable answer from Deesram : https://mcmap.net/q/1215119/-transparent-backgrounds-on-buttons-in-tkinterHieronymus
OK. It looks like might work to some degree — I'll play around with it and get back to you.Superable
S
2

Good news! I was able to get that answer to a related question you found to work. To make it easier to reuse I've converted it into a formal class and added a couple of methods. In addition I made it flash the image off and back on when it's clicked to give the user some visual feedback like "real" tkinter Buttons do.

Note that it responds to mouse button <ButtonRelease-1> events. That's a better choice in most cases than the <Button-1> event because if the user accidentally presses the button, they can move the mouse off the widget image to avoid setting off the event.

Turns out that using the PIL module was unnecessary. Here's the code:

import tkinter as tk  # PEP 8 recommends avoiding `import *`.


class CanvasButton:
    """ Create leftmost 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_path, command, state=tk.NORMAL):
        self.canvas = canvas
        self.btn_image = tk.PhotoImage(file=image_path)
        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)


BGR_IMG_PATH = "sunset_background.png"
BUTTON_IMG_PATH = "alarm_button.png"

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

root = tk.Tk()

background_img = tk.PhotoImage(file=BGR_IMG_PATH)
bgr_width, bgr_height = background_img.width(), background_img.height()

root.geometry(f'{bgr_width}x{bgr_height}')
root.title("TKinter button over transparent background")
root.configure(bg="white")

canvas = tk.Canvas(root, bg="white", height=bgr_height, width=bgr_width, bd=0,
                   highlightthickness=0, relief="ridge")
canvas.place(x=0, y=0)

background = canvas.create_image(0, 0, anchor='nw', image=background_img)

canvas_btn1 = CanvasButton(canvas, 0, 128, BUTTON_IMG_PATH, btn_clicked)
canvas_btn2 = CanvasButton(canvas, 0, 256, BUTTON_IMG_PATH, btn_clicked)

root.resizable(False, False)
root.mainloop()

Screenshot of the result:

Screenshot of the result

Close up:

screenshot of close up

Superable answered 6/2, 2022 at 20:23 Comment(1)
…I did notice however that you're not using f-strings correctly (or doing so unnecessarily) though. They don't do anything unless there are {} brackets in the string that contain a variable name or expression.Superable

© 2022 - 2024 — McMap. All rights reserved.