How to move text inside canvas in Tkinter

Viewed 1500

I got problem in move the text with respect to mouse cursor inside the canvas.

On clicking the text with mouse button 1 and then on dragging the mouse the whole canvas is moved instead of the text inside

What should I do to correct this?

Here is my code :

from tkinter import* 
import tkinter as tk 

root = Tk()   
root.geometry('1000x600+500+100')
root.resizable(False,False)

def drag_start(event):
    widget = event.widget
    widget.startX = event.x
    widget.startY = event.y

def mov(event):
    widget = event.widget
    x = widget.winfo_x() - widget.startX + event.x
    y = widget.winfo_y() - widget.startY + event.y
    canvas.move(obj,x,y)
    canvas.update()

canvas=Canvas(root,width=
800,height=600,bg="red")

canvas.pack(fill=BOTH,
expand=1)

obj=canvas.create_text(100,
50,text="Object",fill=
'blue',font=('Gotham Medium',30,"bold"),anchor="nw")

canvas.tag_bind(obj,"<Button-1>",drag_start)
canvas.tag_bind(obj,'<B1-Motion>',mov)

root.mainloop()
2 Answers

Since canvas.move() is relative to previous position, you need to update the previous position (startX and startY):

def drag_start(event):
    widget = event.widget
    widget.startX, widget.startY = event.x, event.y

def mov(event):
    widget = event.widget
    widget.move(obj, event.x-widget.startX, event.y-widget.startY)
    widget.startX, widget.startY = event.x, event.y # update previous position

Or use canvas.coords():

def drag_start(event):
    widget = event.widget
    x, y = widget.coords(obj)
    # save the offset of the click position from the obj's top-left corner
    widget.dx, widget.dy = event.x-x, event.y-y

def mov(event):
    widget = event.widget
    widget.coords(obj, (event.x-widget.dx, event.y-widget.dy))

There was just one small mistake in the mov() function. You need to update the X and Y starting positions, once the text has been moved a little. Otherwise, it will always move relative to the first position and exponentially take up velocity until it is out of the canvas.

def mov(event):
    widget = event.widget
    x = widget.winfo_x() - widget.startX + event.x
    y = widget.winfo_y() - widget.startY + event.y
    canvas.move(obj,x,y)
    widget.startX = event.x
    widget.startY = event.y
    canvas.update()

This should fix it and you can move the text around.

Related