Moving widgets in Tkinter

Discussion in 'Python' started by Adonis, Jan 11, 2004.

  1. Adonis

    Adonis Guest

    I wish to manually move widgets in Tkinter, now I have successfully done it,
    but with odd results, I would like to move the widgets with a much smoother
    manner, and better precision.

    Any help is greatly appreciated.

    --

    here is snip of working code:

    from Tkinter import *

    class blah:

    def MoveWindow(self, event):
    self.root.update_idletasks()
    self.f.place_configure(x=event.x_root, y=event.y_root-20)

    def __init__(self):
    self.root = Tk()
    self.root.title("...")
    self.root.resizable(0,0)
    self.root.geometry("%dx%d%+d%+d"%(640, 480, 0, 0))

    self.f = Frame(self.root, bd=1, relief=SUNKEN)
    self.f.place(x=0, y=0, width=200, height=200)

    self.l = Label(self.f, bd=1, relief=RAISED, text="Test")
    self.l.pack(fill=X, padx=1, pady=1)

    self.l.bind('<B1-Motion>', self.MoveWindow)
    self.f.bind('<B1-Motion>', self.MoveWindow)

    self.root.mainloop()

    x = blah()
    Adonis, Jan 11, 2004
    #1
    1. Advertising

  2. Adonis

    Eric Brunel Guest

    Adonis wrote:
    > I wish to manually move widgets in Tkinter, now I have successfully done it,
    > but with odd results, I would like to move the widgets with a much smoother
    > manner, and better precision.
    >
    > Any help is greatly appreciated.
    >
    > --
    >
    > here is snip of working code:
    >
    > from Tkinter import *
    >
    > class blah:
    >
    > def MoveWindow(self, event):
    > self.root.update_idletasks()
    > self.f.place_configure(x=event.x_root, y=event.y_root-20)


    event.x_root & event.y_root will give you the coordinates of the event in the
    *screen*, which is apparently not what you want. The name "root" traditionally
    used for Tkinter main windows is somewhat confusing here: the window called
    "root" in tk/Tkinter methods is the screen, not your main window.

    > def __init__(self):
    > self.root = Tk()
    > self.root.title("...")
    > self.root.resizable(0,0)
    > self.root.geometry("%dx%d%+d%+d"%(640, 480, 0, 0))
    >
    > self.f = Frame(self.root, bd=1, relief=SUNKEN)
    > self.f.place(x=0, y=0, width=200, height=200)
    >
    > self.l = Label(self.f, bd=1, relief=RAISED, text="Test")
    > self.l.pack(fill=X, padx=1, pady=1)
    >
    > self.l.bind('<B1-Motion>', self.MoveWindow)
    > self.f.bind('<B1-Motion>', self.MoveWindow)
    >
    > self.root.mainloop()
    >
    > x = blah()


    Doing what you want is a bit more complicated than what you've already done: the
    best way to use event.x_root and event.y_root here is relatively to a former
    recorded position. What I'd do would be the following:

    -----------------------------------------
    from Tkinter import *

    class blah:

    def startMoveWindow(self, event):
    ## When the movement starts, record current root coordinates
    self.__lastX, self.__lastY = event.x_root, event.y_root

    def MoveWindow(self, event):
    self.root.update_idletasks()
    ## Use root coordinates to compute offset for inside window coordinates
    self.__winX += event.x_root - self.__lastX
    self.__winY += event.y_root - self.__lastY
    ## Remember last coordinates
    self.__lastX, self.__lastY = event.x_root, event.y_root
    ## Move inside window
    self.f.place_configure(x=self.__winX, y=self.__winY)

    def __init__(self):
    self.root = Tk()
    self.root.title("...")
    self.root.resizable(0,0)
    self.root.geometry("%dx%d%+d%+d"%(640, 480, 0, 0))

    ## Record coordinates for window to avoid asking them every time
    self.__winX, self.__winY = 0, 0
    self.f = Frame(self.root, bd=1, relief=SUNKEN)
    self.f.place(x=self.__winX, y=self.__winY, width=200, height=200)

    self.l = Label(self.f, bd=1, relief=RAISED, text="Test")
    self.l.pack(fill=X, padx=1, pady=1)

    ## When the button is pressed, make sure we get the first coordinates
    self.l.bind('<ButtonPress-1>', self.startMoveWindow)
    self.l.bind('<B1-Motion>', self.MoveWindow)
    self.f.bind('<ButtonPress-1>', self.startMoveWindow)
    self.f.bind('<B1-Motion>', self.MoveWindow)

    self.root.mainloop()

    x = blah()
    -----------------------------------------

    HTH
    --
    - Eric Brunel <eric dot brunel at pragmadev dot com> -
    PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com
    Eric Brunel, Jan 12, 2004
    #2
    1. Advertising

  3. Adonis

    Adonis Guest

    Thanks a million, works like a charm!

    Just another problem arose *grumble*, trying to get it to work with multiple
    frames, almost there but no cigar.

    Adonis
    Adonis, Jan 12, 2004
    #3
  4. Adonis

    Jeff Epler Guest

    I've embellished your program a little bit ...

    from Tkinter import *

    def clamp(lo, hi, x):
    return min(max(x, lo), hi)

    class blah:
    all = []
    def MoveWindowStart(self, event):
    self.move_lastx = event.x_root
    self.move_lasty = event.y_root
    self.focus()
    def MoveWindow(self, event):
    self.root.update_idletasks()

    dx = event.x_root - self.move_lastx
    dy = event.y_root - self.move_lasty
    self.move_lastx = event.x_root
    self.move_lasty = event.y_root
    self.x = clamp(0, 640-200, self.x + dx) # should depend on
    self.y = clamp(0, 480-200, self.y + dy) # actual size here
    self.f.place_configure(x=self.x, y=self.y)

    def __init__(self, root, title, x, y):
    self.root = root

    self.x = x; self.y = y
    self.f = Frame(self.root, bd=1, relief=RAISED)
    self.f.place(x=x, y=y, width=200, height=200)

    self.l = Label(self.f, bd=1, bg="#08246b", fg="white",text=title)
    self.l.pack(fill=X)

    self.l.bind('<1>', self.MoveWindowStart)
    self.f.bind('<1>', self.focus)
    self.l.bind('<B1-Motion>', self.MoveWindow)
    # self.f.bind('<B1-Motion>', self.MoveWindow)
    self.all.append(self)
    self.focus()

    def focus(self, event=None):
    self.f.tkraise()
    for w in self.all:
    if w is self:
    w.l.configure(bg="#08246b", fg="white")
    else:
    w.l.configure(bg="#d9d9d9", fg="black")



    root = Tk()
    root.title("...")
    root.resizable(0,0)
    root.geometry("%dx%d%+d%+d"%(640, 480, 0, 0))
    x = blah(root, "Window 1", 10, 10)
    y = blah(root, "Window 2", 220, 10)
    y = blah(root, "Window 3", 10, 220)
    root.mainloop()
    Jeff Epler, Jan 12, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?ISO-8859-1?Q?Mickel_Gr=F6nroos?=

    Placing entry widgets on a canvas in Tkinter

    =?ISO-8859-1?Q?Mickel_Gr=F6nroos?=, Jun 30, 2003, in forum: Python
    Replies:
    0
    Views:
    410
    =?ISO-8859-1?Q?Mickel_Gr=F6nroos?=
    Jun 30, 2003
  2. =?ISO-8859-1?Q?Mickel_Gr=F6nroos?=

    Re: Placing entry widgets on a canvas in Tkinter

    =?ISO-8859-1?Q?Mickel_Gr=F6nroos?=, Jun 30, 2003, in forum: Python
    Replies:
    0
    Views:
    951
    =?ISO-8859-1?Q?Mickel_Gr=F6nroos?=
    Jun 30, 2003
  3. Marcus Schneider

    Modifying TKinter widgets defined in Modules

    Marcus Schneider, Aug 15, 2003, in forum: Python
    Replies:
    2
    Views:
    413
    Marcus Schneider
    Aug 16, 2003
  4. Dean

    XP styled Tkinter widgets

    Dean, Oct 20, 2003, in forum: Python
    Replies:
    1
    Views:
    409
    Jeff Hobbs
    Oct 20, 2003
  5. Replies:
    0
    Views:
    555
Loading...

Share This Page