消耗tkinter鼠标事件

时间:2018-05-01 15:01:17

标签: python tkinter tkinter-canvas

鼠标点击后,我在画布上有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 :(得分:1)

当canvas和canvas项都绑定到事件时,没有机制阻止窗口小部件处理事件。

从规范文档:

  

如果使用bind命令为画布窗口创建了绑定,则除了使用bind widget命令为画布项创建的绑定外,还会调用它们。在整个窗口的任何绑定之前,将调用项目的绑定。

由于首先调用了对项的绑定,因此一种解决方案是使用窗口小部件绑定可以使用的变量来知道它应该忽略该事件。

另一个解决方案是绑定到画布项,并让所有处理都来自与小部件的绑定。在绑定函数中,您可以向画布询问单击了哪个项目,然后在单击某些内容时执行特定于项目的功能。

以下是第二种技术的示例:

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

答案 1 :(得分:0)

这里的内容与@Bryan Oakley answer中提到的第二种技术非常类似,只是 将事件处理程序绑定到每个画布项,而不是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()