Rushy Panchal
Rushy Panchal

Reputation: 17532

Position a window in Tkinter based off of mouse event

I am trying to create a Calltip (what IDLE creates when you enter and keep an open parenthesis):

class Calltip:
    '''Creates a window similar to IDLE's call-tips'''
    def __init__(self, widget, text, howLong = 100):
        self.widget, self.text, self.howLong = widget, text, howLong
        self.master = Toplevel(self.widget)
        self.master.wm_overrideredirect(1)
        self.label = Label(self.master, text = self.text)
        self.label.pack()
        self.label.update()
        self.x, self.y, self.posX, self.posY = self.label.winfo_width(), self.label.winfo_height(), self.widget.winfo_rootx(), self.widget.winfo_rooty()
        self.master.geometry("{xSize}x{ySize}+{x}+{y}".format(xSize = self.y, ySize = self.x, x = self.posX, y = self.posY))
        self.widget.bind("<Enter>", (lambda event: self.show(event)))

    def show(self, event):
        '''Shows the calltip'''
        print 'called'
        self.__init__(self.widget, self.text, self.howLong)
        self.master.geometry("+{x}+{y}".format(x = event.x_root, y = event.y_root))
        time.sleep(self.howLong/100)
        self.hide()

    def hide(self):
        '''Hides the calltip'''
        self.master.destroy()

I want it to show wherever the mouse is... However, it always appears in the left corner of my screen... Any reason why, and how can I fix this?

Upvotes: 0

Views: 174

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 385970

I don't know if this is specifically the problem or not, but one problem is definitely that you are calling __init__ more than once. That method should only ever be called once automatically when the object is instantiated. I'm not sure what else is happening under the covers (probably nothing good), but this causes a new Toplevel window to be created every time you show the calltip, effectively creating a memory leak.

Another problem is that you're calling sleep. You should never call sleep in a GUI because it will do exactly that: cause your whole program to freeze. Instead, use after to arrange for the window to be hidden at some point in the future.

Upvotes: 1

Related Questions