Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

make a clean background with an image with Tkinter in python

I'm currently trying to build an app in python with Tkinter, and I'm trying to use an image as a background. I've been able to do that, but when I add other widgets (like frames and labels), their own background overlaps the first one, and the result is not really pleasant. I've search a bit, but I didn't find a way to avoid this. Is it possible ? This is my code :

import tkinter as tk
from PIL import ImageTk, Image

root = tk.Tk()
root.geometry("1280x720")
root.update()

background_img = Image.open("./background.jpg")
background_img = background_img.resize((root.winfo_width(),root.winfo_height()), Image.ANTIALIAS)
background_tkimg = ImageTk.PhotoImage(background_img)

background_label = tk.Label(root, image=background_tkimg)
background_label.place(x=0, y=0, relwidth=1, relheight=1)

frame = tk.Frame(root)
frame.place(anchor="c", relx=.5, rely=.5)

title_label = tk.Label(frame, text="TITLE")
button1 = tk.Button(frame, text="button 1")
button2 = tk.Button(frame, text="button 2")
button3 = tk.Button(frame, text="button 3")

title_label.grid(row=0, column=1, pady=30)
button1.grid(row=1, column=0, padx=20, pady=10)
button2.grid(row=1, column=1, padx=20, pady=10)
button3.grid(row=1, column=2, padx=20, pady=10)

root.mainloop()

And when I run it, I have this window : screen of the window

like image 758
larticho Avatar asked Jun 22 '26 02:06

larticho


2 Answers

This effect can be achieved by using the Tkinter canvas and placing the widgets using .create_window():

import tkinter as tk
from PIL import ImageTk, Image

root = tk.Tk()
root.geometry("1280x720")
root.update()

background_img = Image.open("./background.jpg")
background_img = background_img.resize((root.winfo_width(),root.winfo_height()), Image.ANTIALIAS)
background_tkimg = ImageTk.PhotoImage(background_img)

canvas = tk.Canvas(root, highlightthickness=0)
canvas.pack(expand = True, fill = "both")
canvas.create_image(0,0, image = background_tkimg, anchor = "nw")

root.update()
canvas_height = canvas.winfo_height()
canvas_width = canvas.winfo_width()

title_label = canvas.create_text((canvas_width//2), (canvas_height//2) - 25, fill = "white", text="TITLE")
button1 = tk.Button(canvas, text="button 1")
button2 = tk.Button(canvas, text="button 2")
button3 = tk.Button(canvas, text="button 3")

canvas.create_window((canvas_width//2) - 75, (canvas_height//2) + 25 , window = button1)
canvas.create_window((canvas_width//2), (canvas_height//2) + 25, window = button2)
canvas.create_window((canvas_width//2) + 75, (canvas_height//2) + 25, window = button3)

root.mainloop()

The label has been replaced with canvas.create_text() for a transparent background. The positioning isn't the same as the original, it's just based off approximate offsets from the centre.

This produces this result:

Code result

like image 180
Henry Avatar answered Jun 24 '26 19:06

Henry


Unfortunately, the only way to avoid this is to use a Canvas and display all other widgets with help of .create_window and similar methods. Moreover, you won't be able to use pack, place and grid geometry managers. Instead, you need to calculate coordinates from the top left corner of the Canvas and create other objects according to them.

import tkinter as tk
from PIL import ImageTk, Image


W, H = 1280, 720
root = tk.Tk()
root.geometry("{}x{}".format(W, H))
root.resizable(False, False)
root.update()

background_img = Image.open("./background.jpg").resize((W, H), Image.ANTIALIAS)
background_tkimg = ImageTk.PhotoImage(background_img)

canv = tk.Canvas(root)
canv.create_image(0, 0, image=background_tkimg, anchor="nw")
canv.place(x=0, y=0, relwidth=1, relheight=1)

canv.create_text(W / 2, H / 2, fill="white", text="TITLE")
for i in range(1, 4):
    canv.create_window(W / 2 - 200 + i * 100, H / 2 + 65, window=tk.Button(canv, text="button {}".format(i)))

root.mainloop()

Note that I have changed the "TITLE" text color (with fill argument) to white, otherwise it is hard to see it on the dark background. Here is a screenshot (with a similar background).

The screenshot

like image 41
Demian Wolf Avatar answered Jun 24 '26 18:06

Demian Wolf