Reputation: 15098
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
Upvotes: 1
Views: 284
Reputation: 12672
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()
Upvotes: 1
Reputation: 8057
The problem in which you running into is that you creating a new tooltip before you sure that there is the last one destroyed. So your reference might be loosed sometimes. To avoid that you need to keep track of the recent and destroy it before crafting a new.
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.recent = None
def add(self,event):
if self.recent != None:
self.recent.destroy()
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)
self.recent=self.master
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()
Upvotes: 1