Search code examples
pythontkinterwidgetfade

Smooth fading of window before closing tkinter python


I made a simple tooltip with tkinter and added a fade effect but then there is problem with code:

import tkinter as tk
import time

class ToolTips():
    def __init__(self,widget,text,triggerkey='<Enter>',releasekey='<Leave>'):
        self.widget = widget
        self.text = text
        self.bg = '#ffffe0'
        self.widget.bind(triggerkey,self.add)
        self.widget.bind(releasekey,self.remove)
        self.widget.bind('<ButtonPress>',self.remove)
        
    def add(self,event):
        self.master = tk.Toplevel(bg=self.bg)
        self.master.geometry(f'+{event.x_root}+{event.y_root}')
        self.master.overrideredirect(1)
        self.master.attributes('-topmost',True)
        self.frame = tk.Frame(self.master,bg=self.bg,highlightbackground="black", highlightcolor="black", highlightthickness=1)
        self.frame.pack()
        self.label = tk.Label(self.frame,text=self.text,bg=self.bg,justify=tk.LEFT)
        self.label.pack(padx=1,pady=3)
    
    def remove(self,*args):
        alpha = self.master.attributes('-alpha')
        if alpha > 0:
            alpha -= 0.5
            self.master.attributes('-alpha',alpha)
            self.master.after(100,self.remove)
        else:
            self.master.destroy()

#USAGE OF CLASS
root = tk.Tk()

l = tk.Label(root,text='Hover',font=('hevletica',21))
l.pack()
l.focus_force()

obj = ToolTips(l,text='There is alot more to this? Are you curious?\nBla Bla...')

root.mainloop()

Here remove() was supposed to give a fade effect, but then its not clean and sometimes if you leave the label and enter the label faster than 100 ms, then the tooltip does not destroy and will stay there for ever till the application is completely exited. So is there any easy way,if not, any way, to achieve a smooth fade for this tooltip. Also feel free to point out other mistakes in the code too :)

The answer here has a fade effect, but I dont seem to be able to implement it with my code.

Thanks in advance :D


Solution

  • Try to use after_cancel. For efficiency, There is no need to create the Toplevel each time when mouse hover this text.Just set the -alpha to 0.

    import tkinter as tk
    import time
    
    
    class ToolTips():
        def __init__(self, widget, text, triggerkey='<Enter>', releasekey='<Leave>'):
            self.widget = widget
            self.text = text
            self.bg = '#ffffe0'
            self.widget.bind(triggerkey, self.add)
            self.widget.bind(releasekey, self.remove)
            self.widget.bind('<ButtonPress>', self.remove)
            self.hide_status = None
    
            self.master = tk.Toplevel(bg=self.bg)
            self.master.overrideredirect(1)
            self.master.attributes('-topmost', True)
            self.frame = tk.Frame(self.master, bg=self.bg, highlightbackground="black", highlightcolor="black",
                                  highlightthickness=1)
            self.frame.pack()
            self.label = tk.Label(self.frame, text=self.text, bg=self.bg, justify=tk.LEFT)
            self.label.pack(padx=1, pady=3)
            self.master.attributes('-alpha', 0)
    
        def add(self, event):
            self.master.attributes('-alpha', 1)
            self.master.geometry(f'+{event.x_root}+{event.y_root}')
    
        def remove(self, event, alpha=1):
            if alpha > 0:
                alpha -= 0.01
                self.master.attributes('-alpha', alpha)
                if self.hide_status:
                    self.master.after_cancel(self.hide_status)
                self.hide_status = self.master.after(10, lambda : self.remove(event=None, alpha=alpha))
            else:
                self.master.attributes('-alpha', 0)
    
    
    # USAGE OF CLASS
    root = tk.Tk()
    
    l = tk.Label(root, text='Hover', font=('hevletica', 21))
    l.pack()
    l.focus_force()
    
    obj = ToolTips(l, text='There is alot more to this? Are you curious?\nBla Bla...')
    
    root.mainloop()