Home > Mobile >  How do I move a Tkinter window smoothly?
How do I move a Tkinter window smoothly?

Time:10-15

The problem I'm facing is simple:
I have a tkinter window with root.overrideredirect(True) and hence, I had to make my own move_window(event) with the corresponding binding. It does work, but the moment I drag it with my mouse, the the window relocates such that the top-left corner of the window is at my mouse location.
What I want:
Smooth dragging like we do with our everyday apps.
Code for window and move function with bindings:

from tkinter import *
import pyautogui as pg

bg_color= '#ededed'

root = Tk()
root.overrideredirect(True)
root.title("Google Drive")
root.geometry("1000x600")
root.update()

# Creating a canvas for placing the squircle shape.
canvas = Canvas(root, height=root.winfo_height(), width=root.winfo_width(), highlightthickness=0)
canvas.pack(fill='both')
canvas.update()

# make a frame for the title bar
title_bar = Frame(canvas, bg=bg_color, relief='raised', bd=0)
title_bar.pack(expand=1,fill='x')
title_bar.update()
# put a close button on the title bar
close_button = Button(title_bar, text='X', command= root.destroy,padx = 2,pady = 2,bd = 0,font="bold",highlightthickness=0)
close_button.pack(side='right')
close_button.update()
# a canvas for the main area of the window
window = Canvas(canvas, bg=bg_color,highlightthickness=0)
window.pack(expand=1,fill='both')
window.update()

# Placing the window in the center of the screen
def place_center(): 
    global x, y
    reso = pg.size()
    rx = reso[0]
    ry = reso[1]
    x = int((rx/2) - (root.winfo_width()/2))
    y = int((ry/2) - (root.winfo_height()/2))
    root.geometry(f" {x} {y}")

# Bind Functions
def move_window(event):
    root.geometry(' {0} {1}'.format(event.x_root, event.y_root))
def change_on_hovering(event):
    global close_button
    close_button['bg']= 'white'
def return_to_normalstate(event):
    global close_button
    close_button['bg']= 'black'

xwin=None
ywin=None

# Bindings
title_bar.bind('<B1-Motion>', move_window)
close_button.bind('<Enter>',change_on_hovering)
close_button.bind('<Leave>',return_to_normalstate)

# Function Calls
place_center()
root.mainloop()

Here's another move function I tried but the window kinda glitches

def move_window(event):
    relx = pg.position().x - root.winfo_x()
    rely = pg.position().y - root.winfo_y()
    root.geometry(' {0} {1}'.format(relx, rely))

Any ideas? I suspect it to be a simple mathematical calculation

CodePudding user response:

You need to compute the distance that the mouse has moved since the last time the event was handled, and then add that change to the current location of the window.

You can do this by first setting a binding on the button click to save the location of the cursor. Then, as the window is moved you need to get the new location, calculate the difference from the old location, and then apply that to the current location of the window.

It looks something like this:

def start_move(event):
    global lastx, lasty
    lastx = event.x_root
    lasty = event.y_root

def move_window(event):
    global lastx, lasty
    deltax = event.x_root - lastx
    deltay = event.y_root - lasty
    x = root.winfo_x()   deltax
    y = root.winfo_y()   deltay
    root.geometry(" %s %s" % (x, y))
    lastx = event.x_root
    lasty = event.y_root

...
title_bar.bind("<ButtonPress-1>", start_move)
title_bar.bind('<B1-Motion>', move_window)
...

CodePudding user response:

You could try something like this:

def move_window(event):
    x = event.x_root - root.winfo_x()
    y = event.y_root - root.winfo_y()
    root.geometry(" %s %s" % (x, y))
  • Related