首页 > 解决方案 > 使用 tkinter 鼠标事件

问题描述

我在画布上点击鼠标有 2 个事件。

一个在画布上...

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

其他在画布上的形状...

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

我遇到的问题是这两个事件都被触发了。有没有办法消耗形状本身的点击事件(希望不使用全局变量)?

标签: pythontkintertkinter-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()

推荐阅读