Aravind Selvan
Aravind Selvan

Reputation: 61

Moving tkinter window

I'm trying to create a window by removing its title bar. I made the window move when the user click and drag using a mouse. Now if I click inside any widget and drag, the window is moving. But I want to the make it move only if the user clicks outside the widgets. Any suggestions will be helpful. Here is my code.

from tkinter import *
    
win = Tk()
win.geometry('200x200')
win.overrideredirect(True)

offsetx = 0
offsety = 0

lst = ['Sample 1', 'Sample 2', 'Sample 3', 'Sample 4']
    
def drag(event):
    x = win.winfo_pointerx() - win.offsetx
    y = win.winfo_pointery() - win.offsety
    win.geometry('+{x}+{y}'.format(x=x,y=y))

def click(event):
    win.offsetx = event.x
    win.offsety = event.y


win.bind('<Button-1>', click)
win.bind('<B1-Motion>', drag)
            
lb1 = Listbox(win)
lb1.pack()

b1 = Button(win, text='Close', command=win.destroy).pack()

for i in range(len(lst)):
    lb1.insert(i, lst[i])

win.mainloop()

Upvotes: 1

Views: 1638

Answers (3)

Bryan Oakley
Bryan Oakley

Reputation: 385970

It seems like the simplest thing to do is just check which window received the event in the drag function, and only do the drag if it's the root window:

def drag(event):
    if event.widget == win:
        x = win.winfo_pointerx() - win.offsetx
        y = win.winfo_pointery() - win.offsety
        win.geometry('+{x}+{y}'.format(x=x,y=y))

Or, if you want to be able to drag while clicking in intermediate windows you could check the class of the widget:

def drag(event):
    window_class = event.widget.winfo_class()
    if window_class in ("Tk", "Toplevel", "Frame"):
        x = win.winfo_pointerx() - win.offsetx
        y = win.winfo_pointery() - win.offsety
        win.geometry('+{x}+{y}'.format(x=x,y=y))

Upvotes: 2

Jason Yang
Jason Yang

Reputation: 13061

Here, I use a Frame as container, not root window. It will show a window, top area is for list box and maybe 10 lines default, bottom area with one button and two box of drak green area. Here click-and-drag on list box and button won't move the window, but those two dark green area work.

enter image description here

from tkinter import *

def mouse_down(event):
    global x, y
    x, y = event.x, event.y

def mouse_up(event):
    global x, y
    x, y = None, None

def mouse_drag(event):
    global x, y
    try:
        deltax = event.x - x
        deltay = event.y - y
        x0 = win.winfo_x() + deltax
        y0 = win.winfo_y() + deltay
        win.geometry("+%s+%s" % (x0, y0))
    except:
        pass

win = Tk()
# win.geometry('200x400')
win.overrideredirect(True)

x, y = None, None

frame = Frame(win, background='#004000')
frame.bind('<ButtonPress-1>', mouse_down)
frame.bind('<B1-Motion>', mouse_drag)
frame.bind('<ButtonRelease-1>', mouse_up)
frame.pack()

list_box = Listbox(frame)
list_box.pack()

button = Button(frame, text='Close', command=win.destroy)
button.pack()

lst = ['Sample 1', 'Sample 2', 'Sample 3', 'Sample 4']
for i, item in enumerate(lst):
    list_box.insert(i, item)

win.mainloop()

Upvotes: 2

Isajah
Isajah

Reputation: 196

how about creating a title bar canvas with tkinter and keybind to the title bar, instead of the whole application?

titlebar_canvas = tk.Canvas(win, height=20, width=200)
titlebar_canvas.pack(side='top')
titlebar_canvas.bind('<Button-1>', click)
titlebar_canvas.bind('<B1-Motion>', drag)

Upvotes: 0

Related Questions