Поглотить событие мыши tkinter - PullRequest
0 голосов
/ 01 мая 2018

У меня на холсте 2 события по щелчку мыши.

один на холсте ...

self.canvas.bind( '<ButtonPress-1>', self.left_mouse_down )

другой по фигуре на холсте ...

self.canvas.tag_bind( self.shape, '<Button-1>', self.on_left_click )

Проблема, с которой я столкнулся, заключается в том, что оба события начинаются. Есть ли способ использовать событие click для самой фигуры (надеюсь, не используя глобальную переменную)?

Ответы [ 2 ]

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

Вот кое-что, что очень похоже на вторую технику, упомянутую в answer @Bryan Oakley, за исключением того, что действительно связывает обработчик событий с каждым элементом холста, а не с самим виджетом Canvas ,

Чтобы обнаружить нажатия кнопок на самом виджете, которого нет ни на одном элементе в нем, сначала добавляется фоновый прямоугольный элемент, который заполняет весь холст, и ему присваивается специальный тег, который позволяет щелкать мышью, не находясь поверх других элементов. элементы на холсте, которые будут обрабатываться как особые случаи (например, вызов другой функции-обработчика события).

import tkinter as tk
import random

BKGR_TAG = '_background'
BKGR_COLOR = 'bisque'
RECT_SIZE = 50
WIDTH, HEIGHT = 400, 400

def on_click(event):
    current = event.widget.find_withtag('current')
    if current:
        item = current[0]
        tags = canvas.gettags(item)
        if BKGR_TAG in tags:
            msg = 'You clicked the background'
            # Do other things like call event handler for whole canvas...
        else:
            color = canvas.itemcget(item, 'fill')
            msg = 'You clicked on item with id %s (%s)' % (item, color)
        label.configure(text=msg)

root = tk.Tk()
label = tk.Label(root, anchor='w')
canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT)
label.pack(side='top', fill='x')
canvas.pack(fill='both', expand=True)

# Create background rect same size as canvas.
bkgr = canvas.create_rectangle(0, 0, WIDTH, HEIGHT, width=0, fill=BKGR_COLOR,
                               tags=BKGR_TAG) # Marked with special tag.
canvas.tag_bind(bkgr, '<ButtonPress-1>', on_click)

for color in ('red', 'orange', 'yellow', 'green', 'blue', 'violet'):
    x0 = random.randint(RECT_SIZE, WIDTH-RECT_SIZE)
    y0 = random.randint(RECT_SIZE, HEIGHT-RECT_SIZE)
    id = canvas.create_rectangle(x0, y0, x0+RECT_SIZE, y0+RECT_SIZE,
                                 outline='black', fill=color)
    canvas.tag_bind(id, '<ButtonPress-1>', on_click)

root.mainloop()
0 голосов
/ 01 мая 2018

Не существует механизма, предотвращающего обработку события виджетом, когда и холст, и элемент холста оба связаны с событием.

Из канонической документации:

Если привязки были созданы для окна холста с помощью команды связывания, то они вызываются в дополнение к привязкам, созданным для элементов холста с помощью команды виджета связывания. Привязки для элементов будут вызываться до любой из привязок для окна в целом.

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

Другим решением будет , а не привязка к элементам холста, и позволить всей обработке исходить от привязки к виджету. В пределах связанной функции вы можете спросить холст, на каком элементе щелкнули, а затем выполнить функцию, специфичную для элемента, если на что-то щелкнули.

Вот пример второй техники:

import tkinter as tk
import random

def on_click(event):
    current = event.widget.find_withtag("current")
    if current:
        item = current[0]
        color = canvas.itemcget(item, "fill")
        label.configure(text="you clicked on item with id %s (%s)" % (item, color))
    else:
        label.configure(text="You didn't click on an item")

root = tk.Tk()
label = tk.Label(root, anchor="w")
canvas = tk.Canvas(root, background="bisque", width=400, height=400)
label.pack(side="top", fill="x")
canvas.pack(fill="both", expand=True)

for color in ("red", "orange", "yellow", "green", "blue", "violet"):
    x0 = random.randint(50, 350)
    y0 = random.randint(50, 350)
    canvas.create_rectangle(x0, y0, x0+50, y0+50, outline="black", fill=color)
    canvas.bind('<ButtonPress-1>', on_click)

root.mainloop()
...