Shafay Asghar
Shafay Asghar

Reputation: 29

Place tkinter canvas shape onto cursor location

I know there have been multiple posts similar to this but the problem I have is extremely unique.

app = tk.TK()

canvas = tk.Canvas(app, width = 600, height = 600)
canvas.pack()
ObjectR = canvas.create_rectangle(10, 200, 50, 200, tag = 'Cursor Location', fill = 'green') 

def keyinput(event):
   #e.x
   #e.y
   canvas.move(ObjectR, e.x, e.y)

app.bind('<B1-Motion>', keyinput)
app.mainloop()

The above program creates a rectangle which then moves according to the pixel the mouse is over. The problem is that with the canvas.move line, it moves the object by e.x and by e.y (like if the mouse is over 342, 563 it will move the square by that much). Can i make it so that it moves the square to those coordinates rather than adding the current coordinates by that value. In case you were wondering, I cannot use canvas.coords or assign my shape with new coordinates or a variable(like instead of 10 it was x1. I cannot do this because of the sheer amount of shapes in my program, it would take ages to rewrite all of them as variables and would lead to many other problems with other functions in my program) because my program has too many of these shapes for me to rewrite and change each of their coordinates to an assigned value. I have to use the move functions as coords ends up resizing my object (though if someone knows a way around this too that would be great). Thank you so much for reading all of this, I've spent the past couple hours researching and trying to get around this problem but have found nothing.

Upvotes: 0

Views: 388

Answers (1)

Thingamabobs
Thingamabobs

Reputation: 8037

With motion things get complicated, but you may are happy with a drag an drop of your item. This can made by this code here:

import tkinter as tk
app = tk.Tk()

canvas = tk.Canvas(app, width = 600, height = 600)
canvas.pack()
ObjectR = canvas.create_rectangle(10, 200, 50, 200, tag = 'Cursor Location', fill = 'green')
start_coords=[]

def keyinput(e):
   startx = e.x
   starty = e.y
   start_coords.append(startx)
   start_coords.append(starty)

def move_it(e):
    x = e.x-start_coords[0]
    y = e.y-start_coords[1]
    canvas.move(ObjectR, x, y)
    start_coords.clear()

canvas.bind('<Button-1>', keyinput)
canvas.bind('<ButtonRelease>', move_it)
app.mainloop()

You should be aware that move takes values and not coords. So if you write canvas.move(item, 10,0) the item moves 10 pixels on the x-axis. So I'm taking the starting point and by release I calculate the difference to move the item to this point.

Let me know if something isnt clear.

the most stabel version I can think of with motion is this:

import tkinter as tk
app = tk.Tk()

canvas = tk.Canvas(app, width = 600, height = 600)
canvas.pack()
ObjectR = canvas.create_rectangle(10, 200, 50, 200, tag = 'Cursor Location', fill = 'green')
start_coords=[]
check = tk.IntVar()
check.set(0) 

def keyinput(e):
   startx = e.x
   starty = e.y
   if check.get() == 0:
       start_coords.clear()
       start_coords.append(startx)
       start_coords.append(starty)
       check.set(1)
       return(start_coords)
   else:
       check.set(0)
       return(start_coords) 

def move_it(e):
    x1,y1 = keyinput(e)
    x = e.x-x1
    y = e.y-y1
    x = x*2
    y = y*2
    canvas.move(ObjectR, x, y)

def stop(e):
    start_coords.clear()
    check.set(0)

canvas.bind('<B1-Motion>',move_it)
canvas.bind('<ButtonRelease>', stop)
app.mainloop()

Upvotes: 1

Related Questions