1. Раз Вам так нравяться классы, то напилите это все в виде класса. Так будет правильнее :)
2. Я хочу предожить немножко другое решение (это решение более адаптивное):
import tkinter
#
#
def Enter_(event):
if event.type == "7":
wdg = event.widget
px = wdg.winfo_x() / float(root.winfo_width())
py = (wdg.winfo_y() + wdg.winfo_height()) / float(root.winfo_height())
ballon.place(relx=px, rely=py, anchor="nw")
else:
ballon.place_forget()
#
root = tkinter.Tk()
root.geometry("400x400+100+100")
#
frame = tkinter.Frame(root, width=400, height=400)
frame.place(relx=0.5, rely=0.5, anchor="center")
button = tkinter.Button(root, text="focus_me")
button.pack()
button.bind("<Enter>", Enter_)
button.bind("<Leave>", Enter_)
#
ballon = tkinter.Label(root, padx=5, pady=5, bg="yellow")
ballon["text"] ="Help to button..."
#
root.mainloop()
3. Это лучше не делать без причины:
self.pupwin.overrideredirect(1)
Так как в этом случае оконный менеджер будет его игнорировать. Кроме того, это решение будет рабоать не на всех операционных системах. В основном такой подход применяется для отображения стартового окна программы с красивым (и не всегда красивым) рисунком :)
Будут вопросы - пишите.