You have two options: fade out the whole window or fade out an image using PIL
, individual widgets cannot be faded out:
Fading out a window
Tk
and TopLevel
windows can be faded out entirely
import time
import threading
import tkinter
root = tkinter.Tk()
def fade():
global root
# Walk backwards through opacities (1 is opaque, 0 is transparent)
i = 1.0
while i >= 0:
root.attributes("-alpha", i)
i -= 0.1
# Sleep some time to make the transition not immediate
time.sleep(0.05)
# Put image fading in a thread so it doesn't block our GUI
fade_thread = threading.Thread(target=fade)
tkinter.Button(root, text="Fade out", command=fade_thread.start).pack()
root.mainloop()
Fading out an image
A bit more involved and a bit more computationally intensive (larger images exacerbate this problem). It could be worth precomputing these or using less steps (-10 vs -5 etc) to save some compute power.
import time
import threading
import tkinter
from PIL import Image, ImageTk
root = tkinter.Tk()
# Tested with .jpg and .png
IMAGE_PATH = "/path/to/image.jpg"
# Create a pillow image and a tkinter image. convert to RGBA to add alpha channel to image
image = Image.open(IMAGE_PATH).convert("RGBA")
image_tk = ImageTk.PhotoImage(image)
# We'll fade to whatever the background is here (black, white, orange, etc)
label = tkinter.Label(root, image=image_tk, bg="black")
label.pack()
def fade_image():
global image, image_tk, label
# Walk backwards through opacities (255 is opaque, 0 is transparent)
for i in range(255, 0, -5):
image.putalpha(i) # Set new alpha
image_tk = ImageTk.PhotoImage(image) # Cretae new image_tk
label.configure(image=image_tk)
# Sleep some time to make the transition not immediate
time.sleep(0.001)
# Put image fading in a thread so it doesn't block our GUI
fade_thread = threading.Thread(target=fade_image)
tkinter.Button(root, text="Fade To Black", command=fade_thread.start).pack()
root.mainloop()
Note this is bad practice in regards to using threads and time.sleep()
inside a GUI program. Using widget.after(delay_in_ms, callback)
is preferable. For more on how to do that check out tkinter: how to use after method