Форум сайта python.su
Необходимо, чтобы несколько объектов посредством одной функции, а не нескольких функций соответствующих количеству объектов, независимо друг от друга двигались по направлению к курсору (в разные точки). В данный момент они движутся в одном направлении. Прошу просветить, как сделать правильно.
from tkinter import* root=Tk() root.title ('Проверка') c = Canvas(width=2250, height=2250,bg='green') c.pack() c.create_polygon(110, 110, 110, 160, 150, 135,tag='треугольник') c.create_rectangle(180,10,280,80, fill='black',tag='прямоугольник') def opred(event): c=event.widget coord_x=c.canvasx(event.x) coord_y=c.canvasy(event.y) item=c.find_closest(coord_x,coord_y) predmet_kortezh=c.gettags(item) global predmet predmet=' '.join(predmet_kortezh[:-1]) coord_x = None coord_y = None def sdvig(event): global coord_x global coord_y x = root.winfo_pointerx() y = root.winfo_pointery() c=event.widget coord_x=c.canvasx(event.x) coord_y=c.canvasy(event.y) def sdvig2(): if c.bbox(predmet)[2]<coord_x and c.bbox(predmet)[3]<coord_y: c.move(predmet,1,1) c.update() c.after(10,sdvig2) c.after(10,sdvig2) c.bind("<ButtonPress-1>", opred) c.bind('<Button-3>',sdvig) root.mainloop()
Отредактировано Konstantin1984+ (Июнь 15, 2025 20:44:35)
Офлайн
Konstantin1984+Непонятно. У вас курсор находится в одной точке? Или у вас несколько курсоров в разных точках? Об'екты должны двигаться к одному курсору или к нескольким разным точкам?
по направлению к курсору (в разные точки)
Офлайн
Видимо, несовсем правильно выразился. Для объектов задаются разные точки назначения, но в настоящий момент получается так, что двигаются они в одном направлении (к одной и той же точке, последней из заданных).
Офлайн
Konstantin1984+Так стало немножко понятнее. Теперь об'ясните, как задаются точки для каждого об'екта?
Для объектов задаются разные точки назначения, но в настоящий момент двигаются они в одном направлении (к точке последней из заданных).
Офлайн
import tkinter as tk class DraggableCanvas(tk.Canvas): def __init__(self, master, **kwargs): super().__init__(master, **kwargs) self.bind("<ButtonPress-1>", self.on_press_1) self.bind("<ButtonPress-3>", self.on_press_3) self._drag_data = {"x": 0, "y": 0, "item": None} # Пример объектов self.create_oval(50, 50, 100, 100, fill="red", tags="draggable") self.create_rectangle(150, 150, 200, 200, fill="blue", tags="draggable") def on_press_1(self, event): # Найти объект под курсором items = self.find_overlapping(event.x, event.y, event.x, event.y) item = None for obj in items[::-1]: # в обратном порядке — верхние объекты первыми if "draggable" in self.gettags(obj): item = obj break # Проверить, можно ли перетаскивать if item: self._drag_data["item"] = item self._drag_data["x"] = event.x self._drag_data["y"] = event.y def on_press_3(self, event): item = self._drag_data["item"] if item: dx = event.x - self._drag_data["x"] dy = event.y - self._drag_data["y"] self.move(item, dx, dy) self._drag_data["x"] = event.x self._drag_data["y"] = event.y self._drag_data["item"] = None if __name__ == "__main__": root = tk.Tk() root.title("Перетаскивание объектов") canvas = DraggableCanvas(root, width=400, height=300, bg="white") canvas.pack(fill="both", expand=True) root.mainloop()
Офлайн
Программа xam1816 предполагает одиночное молниеносное смещение выделенного объекта в назначенную мышью точку, при этом для последующего смещения нужно снова нажимать на объект. Я предполагаю более сложную задачу, сначала левой кнопкой мыши выделяется объект, потом ему задается правой кнопкой точка, к которой двигаться, и объект постепенно смещается, в процессе можно задавать новые точки (правой кнопкой мыши) и объект будет продолжать движение. Проблема в том, чтобы два (или более объектов, в примере их два, но программа должна работать при любом количестве объектов) объекта двигались одновременно и независимо друг от друга (выделяем один объект левой кнопкой мыши и задаем направление правой, повторяем тоже со вторым, и они двигаются одновременно).
Офлайн
import tkinter as tk import math class DraggableCanvas(tk.Canvas): def __init__(self, master, **kwargs): super().__init__(master, **kwargs) self.bind("<ButtonPress-1>", self.on_left_press) self.bind("<ButtonPress-3>", self.on_right_press) self.bind("<ButtonRelease-3>", self.on_right_release) self.selected_item = None self.move_targets = {} # item_id -> (target_x, target_y) self.moving_items = set() # item_id -> currently animating # Пример объектов self.create_oval(50, 50, 100, 100, fill="red", tags="draggable") self.create_rectangle(150, 150, 200, 200, fill="blue", tags="draggable") def on_left_press(self, event): items = self.find_overlapping(event.x, event.y, event.x, event.y) for item in reversed(items): if "draggable" in self.gettags(item): self.selected_item = item break def on_right_press(self, event): if self.selected_item: self.move_targets[self.selected_item] = (event.x, event.y) def on_right_release(self, event): if self.selected_item and self.selected_item in self.move_targets: if self.selected_item not in self.moving_items: self.moving_items.add(self.selected_item) self.animate_move(self.selected_item) def animate_move(self, item_id, speed=1): if item_id not in self.move_targets: self.moving_items.discard(item_id) return target_x, target_y = self.move_targets[item_id] coords = self.bbox(item_id) if coords is None: self.moving_items.discard(item_id) return x0 = (coords[0] + coords[2]) / 2 y0 = (coords[1] + coords[3]) / 2 dx = target_x - x0 dy = target_y - y0 distance = math.hypot(dx, dy) if distance < 5: self.moving_items.discard(item_id) return step_x = dx / distance * speed step_y = dy / distance * speed self.move(item_id, step_x, step_y) self.after(20, lambda: self.animate_move(item_id, speed)) if __name__ == "__main__": root = tk.Tk() root.title("Плавное перемещение объектов") canvas = DraggableCanvas(root, width=500, height=400, bg="white") canvas.pack(fill="both", expand=True) root.mainloop()
Отредактировано xam1816 (Июнь 17, 2025 20:19:50)
Офлайн
Интересный вариант. Буду осмыслять. Спасибо.
Офлайн