0

Good Afternoon,

I've been attempting to implement the script from this page: Tkinter: Mouse drag a window without borders, eg. overridedirect(1)

To work with my tkinter top Level window. This is how my tkinter window is initialized:

    def __init__(self, master=None):
        tkinter.Tk.__init__(self, master)

I then hide the root window and start up a top level window. Which i'm doing so that I can currently minimize and re-open the top level window.

    #Hide Root
    self.attributes("-alpha",0.0)
    self.attributes("-topmost", True)

    #Top Level Window
    top_level = tkinter.Toplevel(self)
    top_level.geometry("600x300")
    top_level.overrideredirect(True)
    top_level.config(bg="#1e1e1e")

Now I try and get the window to move using this chunk of code here from the page listed above. (I've changed some of the variables to match my window)

    top_level.bind("<ButtonPress-1>", top_level.StartMove)
    top_level.bind("<ButtonRelease-1>", top_level.StopMove)
    top_level.bind("<B1-Motion>", top_level.OnMotion)

def StartMove(top_level, event):
    top_level.x = event.x
    top_level.y = event.y

def StopMove(top_level, event):
    top_level.x = None
    top_level.y = None

def OnMotion(top_level, event):
    deltax = event.x - top_level.x
    deltay = event.y - top_level.y
    x = top_level.winfo_x() + deltax
    y = top_level.winfo_y() + deltay
    top_level.geometry("+%s+%s" % (x, y))

This is the error that I receive:

Traceback (most recent call last):
  File "E:/Programs/TestGUI/script_gui.py", line 2, in <module>
    import authenticator
  File "E:\Programs\TestGUI\authenticator.py", line 148, in <module>
    root = Win()
  File "E:\Programs\TestGUI\authenticator.py", line 127, in __init__
    top_level.bind("<ButtonPress-1>", top_level.StartMove)
AttributeError: 'Toplevel' object has no attribute 'StartMove'

Any help would be greatly appreciated as this is one of the last things I need to do to finish this project.

Thanks

1 Answers1

1

According to the error message, you have a class name Win which is derived from tkinter.Tk. So all the functions in the posted code are inside that class.

Then the three lines:

top_level.bind("<ButtonPress-1>", top_level.StartMove)
top_level.bind("<ButtonRelease-1>", top_level.StopMove)
top_level.bind("<B1-Motion>", top_level.OnMotion)

should be changed to:

self.top_level.bind("<ButtonPress-1>", self.StartMove)
self.top_level.bind("<ButtonRelease-1>", self.StopMove)
self.top_level.bind("<B1-Motion>", self.OnMotion)

top_level should be better an instance variable of the class so that it can be accessed by other class methods:

self.top_level = tkinter.Toplevel(self)
self.top_level.geometry('600x300')
self.top_level.overrideredirect(1)
self.top_level.config(bg='#1e1e1e')

Also normally the name of the first argument of class methods StartMove(), StopMove() and OnMotion() is self. And those functions should be modified to cater the change of top_level from local variable to instance variable:

def StartMove(self, event):
    self.top_level.x = event.x
    self.top_level.y = event.y

def StopMove(self, event):
    self.top_level.x = self.top_level.y = None

def OnMotion(self, event):
    deltax = event.x - self.top_level.x
    deltay = event.y - self.top_level.y
    x = self.top_level.winfo_x() + deltax
    y = self.top_level.winfo_y() + deltay
    self.top_level.geometry('+%s+%s' % (x, y))

Below is the definition of the class Win:

class Win(tkinter.Tk):
    def __init__(self):
        tkinter.Tk.__init__(self)
        #Hide Root
        self.attributes('-alpha', 0.0)
        self.attributes('-topmost', 1)

        #Top Level Window
        self.top_level = tkinter.Toplevel(self)
        self.top_level.geometry('600x300')
        self.top_level.overrideredirect(1)
        self.top_level.config(bg='#1e1e1e')
        self.top_level.bind('<ButtonPress-1>', self.StartMove)
        self.top_level.bind('<ButtonRelease-1>', self.StopMove)
        self.top_level.bind('<B1-Motion>', self.OnMotion)

    def StartMove(self, event):
        self.top_level.x = event.x
        self.top_level.y = event.y

    def StopMove(self, event):
        self.top_level.x = self.top_level.y = None

    def OnMotion(self, event):
        deltax = event.x - self.top_level.x
        deltay = event.y - self.top_level.y
        x = self.top_level.winfo_x() + deltax
        y = self.top_level.winfo_y() + deltay
        self.top_level.geometry('+%s+%s' % (x, y))
acw1668
  • 40,144
  • 5
  • 22
  • 34