I'm using tkinter-tooltip and when I try to add a tooltip to a button consisting of only an image, it says "NoneType' object has no attribute 'bind'". It works if I do text=" " but I don't wanna make the text a space or anything, because its shape gets distorted. I just want to add a tooltip to image, is there any way to override this?
import customtkinter
from PIL import Image
from tktooltip import ToolTip
root = customtkinter.CTk()
icon = customtkinter.CTkImage(dark_image=Image.open("icon.png"))
button = customtkinter.CTkButton(master=root, width=10, height=10, text="", image=icon)
button.pack(pady=20, padx=20)
ToolTip(button, msg="A message", delay=0, follow=True,
parent_kwargs={"bg": "black", "padx": 3, "pady": 3},
fg="white", bg="orange", padx=7, pady=7)
root.mainloop()
Traceback (most recent call last):
File "d:\Python Projects\main.py", line 10, in <module>
ToolTip(button, msg="A message", delay=0, follow=True,
File "D:\Python311\Lib\site-packages\tktooltip\tooltip.py", line 83, in __init__
self.widget.bind("<Enter>", self.on_enter, add=" ")
File "D:\Python311\Lib\site-packages\customtkinter\windows\widgets\ctk_button.py", line 544, in bind
self._text_label.bind(sequence, command, add=True)
^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'bind'
CodePudding user response:
As Bryan said, it is a bug in customtkinter
that when text
option is an empty string, the internal label self._text_label
will not be created and so it is None
. You can overcome this by setting text=" "
instead.
Also it is better not to set delay=0
in ToolTip(...)
as it will make the tooltip not showing sometimes. Just give delay
a very small value like 0.01
for example.
import customtkinter
from PIL import Image
from tktooltip import ToolTip
root = customtkinter.CTk()
icon = customtkinter.CTkImage(dark_image=Image.open("icon.png"))
# set text=" "
button = customtkinter.CTkButton(master=root, width=10, height=10, text=" ", image=icon)
button.pack(pady=20, padx=20)
# set delay=0.01
ToolTip(button, msg="A message", delay=0.01, follow=True,
parent_kwargs={"bg": "black", "padx": 3, "pady": 3},
fg="white", bg="orange", padx=7, pady=7)
root.mainloop()
Another option is to create a custom CTkButton
class and override the bind()
function:
class MyButton(customtkinter.CTkButton):
def bind(self, sequence=None, command=None, add=True):
if not (add == " " or add is True):
raise ValueError("'add' argument can only be ' ' or True to preserve internal callbacks")
self._canvas.bind(sequence, command, add=True)
if self._text_label:
self._text_label.bind(sequence, command, add=True)
if self._image_label:
self._image_label.bind(sequence, command, add=True)
...
button = MyButton(master=root, width=20, height=20, text="", image=icon)
...