Moving widgets in Tkinter

A

Adonis

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()
 
E

Eric Brunel

Adonis said:
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()
 
A

Adonis

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
 
J

Jeff Epler

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()
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top