Python / Tkinter - 点击时识别对象

时间:2016-08-16 18:45:07

标签: python canvas tkinter onclick

我正在尝试创建一个程序,根据以前的颜色,在点击时将对象颜色从白色变为黑色或从白色变为黑色。我希望程序只在对象是矩形时才改变颜色。我怎样才能做到这一点?

这是我的代码:

import tkinter as tk

root = tk.Tk()

cv = tk.Canvas(root, height=800, width=800)
cv.pack()

def onclick(event):
    item = cv.find_closest(event.x, event.y)

    current_color = cv.itemcget(item, 'fill')

    if current_color == 'black':
        cv.itemconfig(item, fill='white')

    else:
        cv.itemconfig(item, fill='black')


cv.bind('<Button-1>', onclick)

cv.create_line(50, 50, 60, 60, width=2)

cv. create_rectangle(80, 80, 100, 100)

root.mainloop()

在此代码中,程序会更改任何对象的填充颜色。我希望它只为矩形改变它。

感谢您的帮助。

4 个答案:

答案 0 :(得分:5)

以下是此问题的三种常见解决方案:

使用项目类型

您可以向画布询问对象的类型:

item_type = cv.type(item)
if item_type == "rectangle":
    # this item is a rectangle
else:
    # this item is NOT a rectangle

使用标签

另一种解决方案是为每个项目提供一个或多个标签。然后,您可以查询当前项目的标签。

首先,在您想要点击的项目中包含一个或多个标签:

cv. create_rectangle(80, 80, 100, 100, tags=("clickable",))

接下来,检查您感兴趣的商品上的标签,然后检查您的商品是否在该商品的标签集中:

tags = cv.itemcget(item, "tags")
if "clickable" in tags:
    # this item has the "clickable" tag
else:
    # this item does NOT have the "clickable" tag

在标签上创建绑定

第三个选项是将绑定附加到标记而不是整个画布。执行此操作时,只有在单击具有给定标记的项目时才会调用您的函数,从而无需进行任何类型的运行时检查:

cv.tag_bind("clickable", "<1>", onclick)

答案 1 :(得分:2)

BPL的解决方案很好。这是另一个不需要任何全局变量的解决方案。 Tkinter中有一个标签系统,可与&#34; class&#34;来自HTML / CSS。它使我们能够将标签列表与图形对象相关联。请参阅item specifiers

这是怎么回事:

import tkinter as tk


def onclick(event):
    global rectangles
    item = cv.find_closest(event.x, event.y)
    if 'rect' in cv.gettags(item):
        current_color = cv.itemcget(item, 'fill')

        if current_color == 'black':
            cv.itemconfig(item, fill='white')
        else:
            cv.itemconfig(item, fill='black')

rectangles = []

root = tk.Tk()
cv = tk.Canvas(root, height=800, width=800)
cv.pack()
cv.bind('<Button-1>', onclick)

id_a = cv.create_line(50, 50, 60, 60, width=2)
id_b = cv.create_rectangle(80, 80, 100, 100, tags=('rect'))

root.mainloop()

我认为它在某种程度上更加面向对象。 ;)

答案 2 :(得分:1)

这个解决方案怎么样:

import tkinter as tk


def onclick(event):
    global rectangles
    item = cv.find_closest(event.x, event.y)
    if item[0] in rectangles:
        current_color = cv.itemcget(item, 'fill')

        if current_color == 'black':
            cv.itemconfig(item, fill='white')
        else:
            cv.itemconfig(item, fill='black')

rectangles = []

root = tk.Tk()
cv = tk.Canvas(root, height=800, width=800)
cv.pack()
cv.bind('<Button-1>', onclick)

id_a = cv.create_line(50, 50, 60, 60, width=2)
id_b = cv.create_rectangle(80, 80, 100, 100)
rectangles.append(id_b)

root.mainloop()

这样做的主要思想是将要更改颜色的项目ID添加到全局数组中(尽管不鼓励使用全局变量)。然后当你用鼠标点击时,itemcget函数会给你最近项的id,所以你需要检查这个id是否在你的矩形项数组中。

答案 3 :(得分:0)

基于this accepted answer,您需要tag_bind您的矩形。此外,您应该为您创建的每个对象分配ID。如果需要重复执行此操作,可以将过程包装在循环或函数中,但基本理论不会更改。 GL与tkinter!