Add Fade-In Animation to Label in CustomTkinter

99 Views Asked by At

I am trying to make a chat app using Tkinter + CustomTkinter, and I wanted to add a fade-in animation to label "promptReply" when it gets placed on the screen

import customtkinter
from customtkinter import *
import tkinter
from PIL import Image

customtkinter.set_appearance_mode("dark")
customtkinter.set_default_color_theme("blue.json")

root = tkinter.Tk()

root.title(" PizzBot")
root.geometry("455x771")
root.resizable(False, False)
root.configure(background="#2C2C2C")
send = Image.open("send.png")
head = Image.open("ChatBot CanvaDesign.png")
pizzaIco = Image.open("pizza.png")
usr = Image.open("user.png")

framePrompt = customtkinter.CTkFrame(root)
framePrompt.pack(side=BOTTOM)
frameChat = customtkinter.CTkScrollableFrame(root, width=430,height=650)
frameChat.pack()

prompt_input = customtkinter.CTkEntry(framePrompt,height=55,width=375,border_width=0,placeholder_text="Type your prompt here",placeholder_text_color=("gray95", "grey"),font=("Poppins", 18),)
prompt_input.grid(column=0, row=0, padx=6, pady=8)
def executeSend():
    customtkinter.CTkLabel(frameChat,text="\n").pack()

    label = customtkinter.CTkLabel(frameChat,text=prompt_input.get(),font=("Poppins", 20,"bold"),anchor="w",width=20,height=35,wraplength="300",justify="left",padx=20,pady=20,text_color="white",fg_color="#3f52ff",corner_radius=20)
    frameChat.configure(width=430,height=700)
    label.pack(anchor="e",padx=10)

    customtkinter.CTkLabel(frameChat,text="\n").pack()

    promptReply = customtkinter.CTkLabel(frameChat,text="Bot Response Goes Here . Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi urna magna, ultrices sit amet auctor sit amet, facilisis in enim. Etiam leo nunc, vulputate vitae sem eu, vehicula laoreet purus. Nam vulputate et lacus vel iaculis. Pellentesque vel eros dui. Quisque consectetur sed felis sed lacinia.",fg_color="white",text_color="#3F52FF",padx=20,pady=20,wraplength="300",justify="left",anchor="w",font=("Quicksand",18),corner_radius=10,)
    promptReply.pack(anchor="w",padx=10) #add fade-in animation to this label "promptReply"

    frameChat.configure(height=600)

    root.after(100,frameChat._parent_canvas.yview_moveto,1)

    customtkinter.CTkFrame(frameChat,fg_color="#2C2C2C",width=410,height=15).pack()
    customtkinter.CTkFrame(frameChat,fg_color="#3F52FF",width=10,height=5).pack()
    customtkinter.CTkLabel(frameChat,text="\n").pack()

btnSend = customtkinter.CTkButton(framePrompt,text="",corner_radius=10,image=CTkImage(light_image=send, dark_image=send),width=55,height=55,command=executeSend)
btnSend.grid(column=1, row=0)

prompt_input.bind("<Return>", lambda event: executeSend())

root.mainloop()

I tried to research but wasnt able to quite find a solution for it

1

There are 1 best solutions below

0
On

I think that tkinter does not support fade-in-out effect. You can write a function that gradually changes the colors from the background color to the wanted colors.

I wrote an example class for fade in effect for CTkLabel:

class FadeInLabel(customtkinter.CTkLabel):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.fields = ('text_color', 'fg_color')
        self.colors = {key: self.cget(key) for key in self.fields }
        self.colors['base'] = self.master.cget('fg_color')
        self.configure(**{key: self.colors['base'] for key in self.fields})
        
        for key, color in self.colors.items():
            if isinstance(color, str):
                rgb_color = self.winfo_rgb(color)
                self.colors[key] = (rgb_color, rgb_color)
            else:
                self.colors[key] = self.winfo_rgb(color[0]), self.winfo_rgb(color[1])
        
        self.transition = 0
        self.change_color()
        
    def get_curr(self, start, end):
        rgb_to_hex = lambda rgb : '#{:02x}{:02x}{:02x}'.format(*[int(val * 255 / 65535) for val in rgb])
        return rgb_to_hex([start[i] + (end[i]-start[i])*self.transition for i in range(3)])
        
    def change_color(self):
        self.configure(
            **{key:(self.get_curr(self.colors['base'][0], self.colors[key][0]),
                    self.get_curr(self.colors['base'][1], self.colors[key][1])) for key in self.fields}
        )
        self.transition += 0.05
        if self.transition < 1:
            self.after(50, self.change_color)

I started the effect in the creation of the object, but if you want, you can also call change_color method in the pack method.

and then you can use:

    promptReply = FadeInLabel(frameChat,text="Bot Response Goes Here . Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi urna magna, ultrices sit amet auctor sit amet, facilisis in enim. Etiam leo nunc, vulputate vitae sem eu, vehicula laoreet purus. Nam vulputate et lacus vel iaculis. Pellentesque vel eros dui. Quisque consectetur sed felis sed lacinia.",fg_color="#FFFFFF",text_color="#3F52FF",padx=20,pady=20,wraplength=300,justify="left",anchor="w",font=("Quicksand",18),corner_radius=10,)

instead of

    promptReply = customtkinter.CTkLabel(frameChat,text="Bot Response Goes Here . Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi urna magna, ultrices sit amet auctor sit amet, facilisis in enim. Etiam leo nunc, vulputate vitae sem eu, vehicula laoreet purus. Nam vulputate et lacus vel iaculis. Pellentesque vel eros dui. Quisque consectetur sed felis sed lacinia.",fg_color="white",text_color="#3F52FF",padx=20,pady=20,wraplength="300",justify="left",anchor="w",font=("Quicksand",18),corner_radius=10,)

And you will see the effect.