Moving widgets in Tkinter

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Adonis

    Moving widgets in Tkinter

    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.updat e_idletasks()
    self.f.place_co nfigure(x=event .x_root, y=event.y_root-20)

    def __init__(self):
    self.root = Tk()
    self.root.title ("...")
    self.root.resiz able(0,0)
    self.root.geome try("%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(fil l=X, padx=1, pady=1)

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

    self.root.mainl oop()

    x = blah()


  • Eric Brunel

    #2
    Re: Moving widgets in Tkinter

    Adonis wrote:[color=blue]
    > 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.updat e_idletasks()
    > self.f.place_co nfigure(x=event .x_root, y=event.y_root-20)[/color]

    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.
    [color=blue]
    > def __init__(self):
    > self.root = Tk()
    > self.root.title ("...")
    > self.root.resiz able(0,0)
    > self.root.geome try("%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(fil l=X, padx=1, pady=1)
    >
    > self.l.bind('<B 1-Motion>', self.MoveWindow )
    > self.f.bind('<B 1-Motion>', self.MoveWindow )
    >
    > self.root.mainl oop()
    >
    > x = blah()[/color]

    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.updat e_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_co nfigure(x=self. __winX, y=self.__winY)

    def __init__(self):
    self.root = Tk()
    self.root.title ("...")
    self.root.resiz able(0,0)
    self.root.geome try("%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(fil l=X, padx=1, pady=1)

    ## When the button is pressed, make sure we get the first coordinates
    self.l.bind('<B uttonPress-1>', self.startMoveW indow)
    self.l.bind('<B 1-Motion>', self.MoveWindow )
    self.f.bind('<B uttonPress-1>', self.startMoveW indow)
    self.f.bind('<B 1-Motion>', self.MoveWindow )

    self.root.mainl oop()

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

    HTH
    --
    - Eric Brunel <eric dot brunel at pragmadev dot com> -
    PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com

    Comment

    • Adonis

      #3
      Re: Moving widgets in Tkinter

      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



      Comment

      • Jeff Epler

        #4
        Re: Moving widgets in Tkinter

        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.updat e_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_co nfigure(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(fil l=X)

        self.l.bind('<1 >', self.MoveWindow Start)
        self.f.bind('<1 >', self.focus)
        self.l.bind('<B 1-Motion>', self.MoveWindow )
        # self.f.bind('<B 1-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(b g="#08246b", fg="white")
        else:
        w.l.configure(b g="#d9d9d9", fg="black")



        root = Tk()
        root.title("... ")
        root.resizable( 0,0)
        root.geometry(" %dx%d%+d%+d"%(6 40, 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()

        Comment

        Working...