Move rectangle on canvas on a custom pixel grid





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















I wrote this piece of code for practicing, it moves my labels while the left mouse button pushed:



def motion(self, event):
delta_x = event.x - self._drag_data["x"]
delta_y = event.y - self._drag_data["y"]

self.canvas.move(self._drag_data["item"], delta_x, delta_y)

self._drag_data["x"] = event.x
self._drag_data["y"] = event.y


Next i try to move the labels on a defined grid of lets say 5 pixels. So it is easier to "snap" the labels directly together.



How do i do this? Is there a way to move the label only every 5 pixels? So every 5 pixels the label jumps under the cursor again.



Here is the example i found where i extracted the function:



import tkinter as tk

class Example(tk.Frame):

def __init__(self, parent):
tk.Frame.__init__(self, parent)

self.canvas = tk.Canvas(width=400, height=400)
self.canvas.pack(fill="both", expand=True)

self._drag_data = {"x": 0, "y": 0, "item": None}

self._create_token((100, 100), "white")

self.canvas.tag_bind("token", "<ButtonPress-1>", self.on_token_press)
self.canvas.tag_bind("token", "<ButtonRelease-1>", self.on_token_release)
self.canvas.tag_bind("token", "<B1-Motion>", self.on_token_motion)

def _create_token(self, coord, color):
(x,y) = coord
self.canvas.create_oval(x-25, y-25, x+25, y+25, outline=color, fill=color, tags="token")

def on_token_press(self, event):
self._drag_data["item"] = self.canvas.find_closest(event.x, event.y)[0]
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y

def on_token_release(self, event):
self._drag_data["item"] = None
self._drag_data["x"] = 0
self._drag_data["y"] = 0

def on_token_motion(self, event):
delta_x = event.x - self._drag_data["x"]
delta_y = event.y - self._drag_data["y"]
self.canvas.move(self._drag_data["item"], delta_x, delta_y)
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y

if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()









share|improve this question































    1















    I wrote this piece of code for practicing, it moves my labels while the left mouse button pushed:



    def motion(self, event):
    delta_x = event.x - self._drag_data["x"]
    delta_y = event.y - self._drag_data["y"]

    self.canvas.move(self._drag_data["item"], delta_x, delta_y)

    self._drag_data["x"] = event.x
    self._drag_data["y"] = event.y


    Next i try to move the labels on a defined grid of lets say 5 pixels. So it is easier to "snap" the labels directly together.



    How do i do this? Is there a way to move the label only every 5 pixels? So every 5 pixels the label jumps under the cursor again.



    Here is the example i found where i extracted the function:



    import tkinter as tk

    class Example(tk.Frame):

    def __init__(self, parent):
    tk.Frame.__init__(self, parent)

    self.canvas = tk.Canvas(width=400, height=400)
    self.canvas.pack(fill="both", expand=True)

    self._drag_data = {"x": 0, "y": 0, "item": None}

    self._create_token((100, 100), "white")

    self.canvas.tag_bind("token", "<ButtonPress-1>", self.on_token_press)
    self.canvas.tag_bind("token", "<ButtonRelease-1>", self.on_token_release)
    self.canvas.tag_bind("token", "<B1-Motion>", self.on_token_motion)

    def _create_token(self, coord, color):
    (x,y) = coord
    self.canvas.create_oval(x-25, y-25, x+25, y+25, outline=color, fill=color, tags="token")

    def on_token_press(self, event):
    self._drag_data["item"] = self.canvas.find_closest(event.x, event.y)[0]
    self._drag_data["x"] = event.x
    self._drag_data["y"] = event.y

    def on_token_release(self, event):
    self._drag_data["item"] = None
    self._drag_data["x"] = 0
    self._drag_data["y"] = 0

    def on_token_motion(self, event):
    delta_x = event.x - self._drag_data["x"]
    delta_y = event.y - self._drag_data["y"]
    self.canvas.move(self._drag_data["item"], delta_x, delta_y)
    self._drag_data["x"] = event.x
    self._drag_data["y"] = event.y

    if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()









    share|improve this question



























      1












      1








      1








      I wrote this piece of code for practicing, it moves my labels while the left mouse button pushed:



      def motion(self, event):
      delta_x = event.x - self._drag_data["x"]
      delta_y = event.y - self._drag_data["y"]

      self.canvas.move(self._drag_data["item"], delta_x, delta_y)

      self._drag_data["x"] = event.x
      self._drag_data["y"] = event.y


      Next i try to move the labels on a defined grid of lets say 5 pixels. So it is easier to "snap" the labels directly together.



      How do i do this? Is there a way to move the label only every 5 pixels? So every 5 pixels the label jumps under the cursor again.



      Here is the example i found where i extracted the function:



      import tkinter as tk

      class Example(tk.Frame):

      def __init__(self, parent):
      tk.Frame.__init__(self, parent)

      self.canvas = tk.Canvas(width=400, height=400)
      self.canvas.pack(fill="both", expand=True)

      self._drag_data = {"x": 0, "y": 0, "item": None}

      self._create_token((100, 100), "white")

      self.canvas.tag_bind("token", "<ButtonPress-1>", self.on_token_press)
      self.canvas.tag_bind("token", "<ButtonRelease-1>", self.on_token_release)
      self.canvas.tag_bind("token", "<B1-Motion>", self.on_token_motion)

      def _create_token(self, coord, color):
      (x,y) = coord
      self.canvas.create_oval(x-25, y-25, x+25, y+25, outline=color, fill=color, tags="token")

      def on_token_press(self, event):
      self._drag_data["item"] = self.canvas.find_closest(event.x, event.y)[0]
      self._drag_data["x"] = event.x
      self._drag_data["y"] = event.y

      def on_token_release(self, event):
      self._drag_data["item"] = None
      self._drag_data["x"] = 0
      self._drag_data["y"] = 0

      def on_token_motion(self, event):
      delta_x = event.x - self._drag_data["x"]
      delta_y = event.y - self._drag_data["y"]
      self.canvas.move(self._drag_data["item"], delta_x, delta_y)
      self._drag_data["x"] = event.x
      self._drag_data["y"] = event.y

      if __name__ == "__main__":
      root = tk.Tk()
      Example(root).pack(fill="both", expand=True)
      root.mainloop()









      share|improve this question
















      I wrote this piece of code for practicing, it moves my labels while the left mouse button pushed:



      def motion(self, event):
      delta_x = event.x - self._drag_data["x"]
      delta_y = event.y - self._drag_data["y"]

      self.canvas.move(self._drag_data["item"], delta_x, delta_y)

      self._drag_data["x"] = event.x
      self._drag_data["y"] = event.y


      Next i try to move the labels on a defined grid of lets say 5 pixels. So it is easier to "snap" the labels directly together.



      How do i do this? Is there a way to move the label only every 5 pixels? So every 5 pixels the label jumps under the cursor again.



      Here is the example i found where i extracted the function:



      import tkinter as tk

      class Example(tk.Frame):

      def __init__(self, parent):
      tk.Frame.__init__(self, parent)

      self.canvas = tk.Canvas(width=400, height=400)
      self.canvas.pack(fill="both", expand=True)

      self._drag_data = {"x": 0, "y": 0, "item": None}

      self._create_token((100, 100), "white")

      self.canvas.tag_bind("token", "<ButtonPress-1>", self.on_token_press)
      self.canvas.tag_bind("token", "<ButtonRelease-1>", self.on_token_release)
      self.canvas.tag_bind("token", "<B1-Motion>", self.on_token_motion)

      def _create_token(self, coord, color):
      (x,y) = coord
      self.canvas.create_oval(x-25, y-25, x+25, y+25, outline=color, fill=color, tags="token")

      def on_token_press(self, event):
      self._drag_data["item"] = self.canvas.find_closest(event.x, event.y)[0]
      self._drag_data["x"] = event.x
      self._drag_data["y"] = event.y

      def on_token_release(self, event):
      self._drag_data["item"] = None
      self._drag_data["x"] = 0
      self._drag_data["y"] = 0

      def on_token_motion(self, event):
      delta_x = event.x - self._drag_data["x"]
      delta_y = event.y - self._drag_data["y"]
      self.canvas.move(self._drag_data["item"], delta_x, delta_y)
      self._drag_data["x"] = event.x
      self._drag_data["y"] = event.y

      if __name__ == "__main__":
      root = tk.Tk()
      Example(root).pack(fill="both", expand=True)
      root.mainloop()






      python canvas tkinter label






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 22 '18 at 21:01









      Filip Młynarski

      2,1241417




      2,1241417










      asked Nov 22 '18 at 19:44









      K-DoeK-Doe

      10714




      10714
























          2 Answers
          2






          active

          oldest

          votes


















          2














          Here we set deltas of x and y to 5 and then check whether mouse position is behind/under our item and if it is we multiply x or y it by -1 to make delta negative so our item will move in direction of our mouse.



          def motion(self, event):
          delta_x = 0
          delta_y = 0
          step = 5

          if abs(event.x - self._drag_data["x"]) >= step:
          delta_x = step
          if abs(event.y - self._drag_data["y"]) >= step:
          delta_y = step

          if event.x < self._drag_data["x"]:
          delta_x *= -1
          if event.y < self._drag_data["y"]:
          delta_y *= -1

          self.canvas.move(self._drag_data["item"], delta_x, delta_y)

          if delta_x != 0:
          self._drag_data["x"] = event.x
          if delta_y != 0:
          self._drag_data["y"] = event.y





          share|improve this answer


























          • It does what i was asking for. I just forgot to write it should move in sync with the cursor. Sorry for that! I move the mouse like 4 pixels nothing happens. if i move it 5 pixels the label should snap to the next 5 pixel grid.

            – K-Doe
            Nov 22 '18 at 20:11











          • Updated, try it now.

            – Filip Młynarski
            Nov 22 '18 at 20:19











          • Now i got some weird movement, sometimes the label moves with the mouse but off target. Sometimes nothing happes.

            – K-Doe
            Nov 22 '18 at 20:23











          • Could you supply enough code that's needed to recreate this problem?

            – Filip Młynarski
            Nov 22 '18 at 20:26






          • 1





            Problem was that we were updating our _drag_data even if we didn't actually moved our canvas, updating answer with that bug fixed.

            – Filip Młynarski
            Nov 22 '18 at 20:53



















          0














          You can simply round the delta_x and delta_y to the closest multiple of the step size:



          def on_token_motion(self, event):
          step = 20

          # Calculate drag distance
          delta_x = event.x - self._drag_data["x"]
          delta_y = event.y - self._drag_data["y"]

          # Round to nearest multiple of step size
          delta_x = int(step * round(float(delta_x)/step))
          delta_y = int(step * round(float(delta_y)/step))

          # Move the object
          self.canvas.move(self._drag_data["item"], delta_x, delta_y)

          # Update _drag_data to the new position
          self._drag_data["x"] = self._drag_data["x"] + delta_x
          self._drag_data["y"] = self._drag_data["y"] + delta_y


          Note that I also changed the _drag_data update. The new position of the object is not equal to event.x anymore, since we snap to the grid. Therefore, we must update it as self._drag_data["x"] + delta_x, which is the old position plus the amount moved.






          share|improve this answer
























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53437249%2fmove-rectangle-on-canvas-on-a-custom-pixel-grid%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            2














            Here we set deltas of x and y to 5 and then check whether mouse position is behind/under our item and if it is we multiply x or y it by -1 to make delta negative so our item will move in direction of our mouse.



            def motion(self, event):
            delta_x = 0
            delta_y = 0
            step = 5

            if abs(event.x - self._drag_data["x"]) >= step:
            delta_x = step
            if abs(event.y - self._drag_data["y"]) >= step:
            delta_y = step

            if event.x < self._drag_data["x"]:
            delta_x *= -1
            if event.y < self._drag_data["y"]:
            delta_y *= -1

            self.canvas.move(self._drag_data["item"], delta_x, delta_y)

            if delta_x != 0:
            self._drag_data["x"] = event.x
            if delta_y != 0:
            self._drag_data["y"] = event.y





            share|improve this answer


























            • It does what i was asking for. I just forgot to write it should move in sync with the cursor. Sorry for that! I move the mouse like 4 pixels nothing happens. if i move it 5 pixels the label should snap to the next 5 pixel grid.

              – K-Doe
              Nov 22 '18 at 20:11











            • Updated, try it now.

              – Filip Młynarski
              Nov 22 '18 at 20:19











            • Now i got some weird movement, sometimes the label moves with the mouse but off target. Sometimes nothing happes.

              – K-Doe
              Nov 22 '18 at 20:23











            • Could you supply enough code that's needed to recreate this problem?

              – Filip Młynarski
              Nov 22 '18 at 20:26






            • 1





              Problem was that we were updating our _drag_data even if we didn't actually moved our canvas, updating answer with that bug fixed.

              – Filip Młynarski
              Nov 22 '18 at 20:53
















            2














            Here we set deltas of x and y to 5 and then check whether mouse position is behind/under our item and if it is we multiply x or y it by -1 to make delta negative so our item will move in direction of our mouse.



            def motion(self, event):
            delta_x = 0
            delta_y = 0
            step = 5

            if abs(event.x - self._drag_data["x"]) >= step:
            delta_x = step
            if abs(event.y - self._drag_data["y"]) >= step:
            delta_y = step

            if event.x < self._drag_data["x"]:
            delta_x *= -1
            if event.y < self._drag_data["y"]:
            delta_y *= -1

            self.canvas.move(self._drag_data["item"], delta_x, delta_y)

            if delta_x != 0:
            self._drag_data["x"] = event.x
            if delta_y != 0:
            self._drag_data["y"] = event.y





            share|improve this answer


























            • It does what i was asking for. I just forgot to write it should move in sync with the cursor. Sorry for that! I move the mouse like 4 pixels nothing happens. if i move it 5 pixels the label should snap to the next 5 pixel grid.

              – K-Doe
              Nov 22 '18 at 20:11











            • Updated, try it now.

              – Filip Młynarski
              Nov 22 '18 at 20:19











            • Now i got some weird movement, sometimes the label moves with the mouse but off target. Sometimes nothing happes.

              – K-Doe
              Nov 22 '18 at 20:23











            • Could you supply enough code that's needed to recreate this problem?

              – Filip Młynarski
              Nov 22 '18 at 20:26






            • 1





              Problem was that we were updating our _drag_data even if we didn't actually moved our canvas, updating answer with that bug fixed.

              – Filip Młynarski
              Nov 22 '18 at 20:53














            2












            2








            2







            Here we set deltas of x and y to 5 and then check whether mouse position is behind/under our item and if it is we multiply x or y it by -1 to make delta negative so our item will move in direction of our mouse.



            def motion(self, event):
            delta_x = 0
            delta_y = 0
            step = 5

            if abs(event.x - self._drag_data["x"]) >= step:
            delta_x = step
            if abs(event.y - self._drag_data["y"]) >= step:
            delta_y = step

            if event.x < self._drag_data["x"]:
            delta_x *= -1
            if event.y < self._drag_data["y"]:
            delta_y *= -1

            self.canvas.move(self._drag_data["item"], delta_x, delta_y)

            if delta_x != 0:
            self._drag_data["x"] = event.x
            if delta_y != 0:
            self._drag_data["y"] = event.y





            share|improve this answer















            Here we set deltas of x and y to 5 and then check whether mouse position is behind/under our item and if it is we multiply x or y it by -1 to make delta negative so our item will move in direction of our mouse.



            def motion(self, event):
            delta_x = 0
            delta_y = 0
            step = 5

            if abs(event.x - self._drag_data["x"]) >= step:
            delta_x = step
            if abs(event.y - self._drag_data["y"]) >= step:
            delta_y = step

            if event.x < self._drag_data["x"]:
            delta_x *= -1
            if event.y < self._drag_data["y"]:
            delta_y *= -1

            self.canvas.move(self._drag_data["item"], delta_x, delta_y)

            if delta_x != 0:
            self._drag_data["x"] = event.x
            if delta_y != 0:
            self._drag_data["y"] = event.y






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 22 '18 at 21:07

























            answered Nov 22 '18 at 19:53









            Filip MłynarskiFilip Młynarski

            2,1241417




            2,1241417













            • It does what i was asking for. I just forgot to write it should move in sync with the cursor. Sorry for that! I move the mouse like 4 pixels nothing happens. if i move it 5 pixels the label should snap to the next 5 pixel grid.

              – K-Doe
              Nov 22 '18 at 20:11











            • Updated, try it now.

              – Filip Młynarski
              Nov 22 '18 at 20:19











            • Now i got some weird movement, sometimes the label moves with the mouse but off target. Sometimes nothing happes.

              – K-Doe
              Nov 22 '18 at 20:23











            • Could you supply enough code that's needed to recreate this problem?

              – Filip Młynarski
              Nov 22 '18 at 20:26






            • 1





              Problem was that we were updating our _drag_data even if we didn't actually moved our canvas, updating answer with that bug fixed.

              – Filip Młynarski
              Nov 22 '18 at 20:53



















            • It does what i was asking for. I just forgot to write it should move in sync with the cursor. Sorry for that! I move the mouse like 4 pixels nothing happens. if i move it 5 pixels the label should snap to the next 5 pixel grid.

              – K-Doe
              Nov 22 '18 at 20:11











            • Updated, try it now.

              – Filip Młynarski
              Nov 22 '18 at 20:19











            • Now i got some weird movement, sometimes the label moves with the mouse but off target. Sometimes nothing happes.

              – K-Doe
              Nov 22 '18 at 20:23











            • Could you supply enough code that's needed to recreate this problem?

              – Filip Młynarski
              Nov 22 '18 at 20:26






            • 1





              Problem was that we were updating our _drag_data even if we didn't actually moved our canvas, updating answer with that bug fixed.

              – Filip Młynarski
              Nov 22 '18 at 20:53

















            It does what i was asking for. I just forgot to write it should move in sync with the cursor. Sorry for that! I move the mouse like 4 pixels nothing happens. if i move it 5 pixels the label should snap to the next 5 pixel grid.

            – K-Doe
            Nov 22 '18 at 20:11





            It does what i was asking for. I just forgot to write it should move in sync with the cursor. Sorry for that! I move the mouse like 4 pixels nothing happens. if i move it 5 pixels the label should snap to the next 5 pixel grid.

            – K-Doe
            Nov 22 '18 at 20:11













            Updated, try it now.

            – Filip Młynarski
            Nov 22 '18 at 20:19





            Updated, try it now.

            – Filip Młynarski
            Nov 22 '18 at 20:19













            Now i got some weird movement, sometimes the label moves with the mouse but off target. Sometimes nothing happes.

            – K-Doe
            Nov 22 '18 at 20:23





            Now i got some weird movement, sometimes the label moves with the mouse but off target. Sometimes nothing happes.

            – K-Doe
            Nov 22 '18 at 20:23













            Could you supply enough code that's needed to recreate this problem?

            – Filip Młynarski
            Nov 22 '18 at 20:26





            Could you supply enough code that's needed to recreate this problem?

            – Filip Młynarski
            Nov 22 '18 at 20:26




            1




            1





            Problem was that we were updating our _drag_data even if we didn't actually moved our canvas, updating answer with that bug fixed.

            – Filip Młynarski
            Nov 22 '18 at 20:53





            Problem was that we were updating our _drag_data even if we didn't actually moved our canvas, updating answer with that bug fixed.

            – Filip Młynarski
            Nov 22 '18 at 20:53













            0














            You can simply round the delta_x and delta_y to the closest multiple of the step size:



            def on_token_motion(self, event):
            step = 20

            # Calculate drag distance
            delta_x = event.x - self._drag_data["x"]
            delta_y = event.y - self._drag_data["y"]

            # Round to nearest multiple of step size
            delta_x = int(step * round(float(delta_x)/step))
            delta_y = int(step * round(float(delta_y)/step))

            # Move the object
            self.canvas.move(self._drag_data["item"], delta_x, delta_y)

            # Update _drag_data to the new position
            self._drag_data["x"] = self._drag_data["x"] + delta_x
            self._drag_data["y"] = self._drag_data["y"] + delta_y


            Note that I also changed the _drag_data update. The new position of the object is not equal to event.x anymore, since we snap to the grid. Therefore, we must update it as self._drag_data["x"] + delta_x, which is the old position plus the amount moved.






            share|improve this answer




























              0














              You can simply round the delta_x and delta_y to the closest multiple of the step size:



              def on_token_motion(self, event):
              step = 20

              # Calculate drag distance
              delta_x = event.x - self._drag_data["x"]
              delta_y = event.y - self._drag_data["y"]

              # Round to nearest multiple of step size
              delta_x = int(step * round(float(delta_x)/step))
              delta_y = int(step * round(float(delta_y)/step))

              # Move the object
              self.canvas.move(self._drag_data["item"], delta_x, delta_y)

              # Update _drag_data to the new position
              self._drag_data["x"] = self._drag_data["x"] + delta_x
              self._drag_data["y"] = self._drag_data["y"] + delta_y


              Note that I also changed the _drag_data update. The new position of the object is not equal to event.x anymore, since we snap to the grid. Therefore, we must update it as self._drag_data["x"] + delta_x, which is the old position plus the amount moved.






              share|improve this answer


























                0












                0








                0







                You can simply round the delta_x and delta_y to the closest multiple of the step size:



                def on_token_motion(self, event):
                step = 20

                # Calculate drag distance
                delta_x = event.x - self._drag_data["x"]
                delta_y = event.y - self._drag_data["y"]

                # Round to nearest multiple of step size
                delta_x = int(step * round(float(delta_x)/step))
                delta_y = int(step * round(float(delta_y)/step))

                # Move the object
                self.canvas.move(self._drag_data["item"], delta_x, delta_y)

                # Update _drag_data to the new position
                self._drag_data["x"] = self._drag_data["x"] + delta_x
                self._drag_data["y"] = self._drag_data["y"] + delta_y


                Note that I also changed the _drag_data update. The new position of the object is not equal to event.x anymore, since we snap to the grid. Therefore, we must update it as self._drag_data["x"] + delta_x, which is the old position plus the amount moved.






                share|improve this answer













                You can simply round the delta_x and delta_y to the closest multiple of the step size:



                def on_token_motion(self, event):
                step = 20

                # Calculate drag distance
                delta_x = event.x - self._drag_data["x"]
                delta_y = event.y - self._drag_data["y"]

                # Round to nearest multiple of step size
                delta_x = int(step * round(float(delta_x)/step))
                delta_y = int(step * round(float(delta_y)/step))

                # Move the object
                self.canvas.move(self._drag_data["item"], delta_x, delta_y)

                # Update _drag_data to the new position
                self._drag_data["x"] = self._drag_data["x"] + delta_x
                self._drag_data["y"] = self._drag_data["y"] + delta_y


                Note that I also changed the _drag_data update. The new position of the object is not equal to event.x anymore, since we snap to the grid. Therefore, we must update it as self._drag_data["x"] + delta_x, which is the old position plus the amount moved.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 23 '18 at 8:59









                fhdrsdgfhdrsdg

                7,38322038




                7,38322038






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53437249%2fmove-rectangle-on-canvas-on-a-custom-pixel-grid%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

                    ComboBox Display Member on multiple fields

                    Is it possible to collect Nectar points via Trainline?