Переместить прямоугольник на холсте по пользовательской сетке пикселей - PullRequest
0 голосов
/ 22 ноября 2018

Я написал этот фрагмент кода для практики, он перемещает мои метки, когда левая кнопка мыши нажата:

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

Далее я пытаюсь переместить метки в определенной сетке, скажем, 5 пикселей.Так что проще «привязать» ярлыки прямо вместе.

Как мне это сделать?Есть ли способ переместить метку только каждые 5 пикселей?Таким образом, каждые 5 пикселей метка снова попадает под курсор.

Вот пример, который я нашел, когда извлек функцию:

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()

Ответы [ 2 ]

0 голосов
/ 23 ноября 2018

Вы можете просто округлить delta_x и delta_y до ближайшего кратного размера шага:

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

Обратите внимание, что я также изменил обновление _drag_data.Новая позиция объекта больше не равна event.x, так как мы привязываемся к сетке.Поэтому мы должны обновить его как self._drag_data["x"] + delta_x, что является старой позицией плюс перемещенная сумма.

0 голосов
/ 22 ноября 2018

Здесь мы устанавливаем дельты x и y равными 5, а затем проверяем, находится ли позиция мыши позади или под нашим элементом, и, если это так, мы умножаем x или y на -1, чтобы сделать дельту отрицательной, чтобы наш элемент двигался в направлениинаша мышь.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...