Как перетащить объект на холст за его угол? А как отделить объекты один раз друг над другом? - PullRequest
0 голосов
/ 17 мая 2018

Я пытаюсь создать простую программу, в которой вы можете перемещать несколько объектов на холсте в tkinter, перетаскивая их. Для начала я начал с 2 квадратов. Однако я сталкиваюсь с 2 проблемами:

  1. каждый раз, когда я нажимаю на объект, он центрируется на указатель мыши (указатель всегда в середине квадрата). Как я могу перетащить объект по месту щелчка (например, перетащить по углу)?

  2. как только я прохожу один квадрат через другой, второй квадрат остается наверху и больше не может быть отделен. Объекты имеют одинаковые размеры.

Есть ли простые решения для этого? Спасибо за любую помощь или совет.

Мой код:

import tkinter
c = tkinter.Canvas(width = 400, height = 300)
c.pack()

d = 25  #size of square
x, x2 = 100, 200
y, y2 = 100, 200

rect = c.create_rectangle(x-d, y-d, x+d, y+d, fill = 'blue')     #first square
rect2 = c.create_rectangle(x2-d, y2-d, x2+d, y2+d, fill = 'red')    #second square

def drag(event): #drag by holding mouse button 1
    global x, y, x2, y2, xt, yt, x2t, y2t
    xt, yt = event.x, event.y   #1st square movement coords
    x2t, y2t = event.x, event.y #2nd square movement coords
    if xt in range(x-d, x+d):
        if yt in range(y-d, y+d):
            c.coords(rect, xt-d, yt-d, xt+d, yt+d)  #coords update of 1st square
            x, y = xt, yt
    if x2t in range(x2-d, x2+d):
        if y2t in range(y2-d, y2+d):
            c.coords(rect2, x2t-d, y2t-d, x2t+d, y2t+d) #coords update of 2nd square
            x2, y2 = x2t, y2t

c.bind('<B1-Motion>', drag)

tkinter.mainloop()

1 Ответ

0 голосов
/ 17 мая 2018

Есть два вопроса:

1 - чтобы захватить объект углом, вам нужно сместить положение объекта на половину его размеров ограничительной рамки.(см. пример, который захватывает объект в правом нижнем углу; вы можете изменить угол, изменив знаки используемых смещений.)

2- Чтобы различать объекты при перетаскивании, вам нужно«деактивировать» обратный вызов, когда объект уже захвачен.Пример показывает, как делать уборку, я думаю, что это необходимо.(но может быть и лучше, встроенный в tkinter, IDK)

import tkinter


captured = None


def capture(event):
    global captured
    print('captured')
    if captured is None:
        captured = event.widget.find_closest(event.x, event.y)


def release(event):
    global captured
    print('released')
    captured = None


def drag(event):   # drag by holding mouse button 1
    global captured
    if captured is None:
        print(f'captured {event.widget.find_closest(event.x, event.y)}')
        captured = event.widget.find_closest(event.x, event.y)
        print(f'captured: {captured}')
    else:
        x0, y0, x1, y1 = c.bbox(captured)
        xt, yt = event.x + (x0 - x1) // 2, event.y + (y0 - y1) // 2      # 1st square movement coords
        c.coords(captured, xt-d, yt-d, xt+d, yt+d)        # coords update of 1st square


if __name__ == '__main__':

    c = tkinter.Canvas(width = 400, height = 300)
    c.pack()

    d = 25   # size of square
    x, x2 = 100, 200
    y, y2 = 100, 200

    rect1 = c.create_rectangle(x-d, y-d, x+d, y+d, fill='blue', tags='r1')        # first square
    rect2 = c.create_rectangle(x2-d, y2-d, x2+d, y2+d, fill='red', tags='r2')    # second square

    c.bind('<Button-1>', capture)
    c.bind('<ButtonRelease-1>', release)
    c.bind('<B1-Motion>', drag)

    tkinter.mainloop()
...