physics123
physics123

Reputation: 33

Drag and drop oval on canvas using Tkinter

I am working on a python program for moving two circles on a canvas with the mousepointer. I have figured out how to attach the motion to the circles, but when I drag it with the mousebutton the circles goes in a weird direction. Their motions should also be separate but now they are entangled.

I have tried to use the built in move-function and e.x and e.y function. Below is my code.

from tkinter import *

class movingCircle:

    def __init__(self):
        self.window = Tk()
        self.window.title("Moving circles")
        self.window.geometry("500x400")

        self.canvas1 = Canvas(self.window, width = 300, height = 300, bg = "grey")
        self.canvas1.pack(pady=30)
        self.circle1 = self.canvas1.create_oval(10, 10, 50, 50, fill="red")
        self.circle2 = self.canvas1.create_oval(100, 100, 70, 70, fill="red")
        self.window.bind("<B1-Motion>", self.move)

        self.window.mainloop()


    def move(self, event):
        self.canvas1.move(self.circle1, event.x, event.y)
        self.canvas1.move(self.circle2, event.x, event.y)

movingCircle()

Upvotes: 3

Views: 518

Answers (1)

Bryan Oakley
Bryan Oakley

Reputation: 386372

self.canvas1.move requires a distance, but you're passing a pixel address.

One solution is to remember the previous pixel location, then in your move function you need to calculate how many pixels the cursor has moved and pass that to self.canvas1.move.

The other problem is that you are explicitly moving all of the items. If you only want to move the one that was clicked on you can use the tag "current".

In the following example based on your code, notice that there's an extra event binding to save the location where you first click, and this value is then used to compute how far the mouse has moved in each direction. Also notice that it only calls move for "current" rather than one of the oval ids.

from tkinter import *

class movingCircle:

    def __init__(self):
        self.window = Tk()
        self.window.title("Moving circles")
        self.window.geometry("500x400")

        self.canvas1 = Canvas(self.window, width = 300, height = 300, bg = "grey")
        self.canvas1.pack(pady=30)
        self.circle1 = self.canvas1.create_oval(10, 10, 50, 50, fill="red")
        self.circle2 = self.canvas1.create_oval(100, 100, 70, 70, fill="red")

        self.window.bind("<ButtonPress-1>", self.start_move)
        self.window.bind("<B1-Motion>", self.move)

        self.window.mainloop()


    def start_move(self, event):
        self._x = event.x
        self._y = event.y

    def move(self, event):
        deltax = event.x - self._x
        deltay = event.y - self._y
        self._x = event.x
        self._y = event.y
        self.canvas1.move("current", deltax, deltay)

movingCircle()

Upvotes: 3

Related Questions