Leero11 Leero11 - 1 year ago 67
Python Question

Python/Tkinter - Identify object on click

I am trying to create a program that changes the object colour on click from white to black or from white to black depending of the previous colour. I would want the program change the colour only if the object is a rectangle. How can I make the this happen?

Here is my code:

import tkinter as tk

root = tk.Tk()

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

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

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)


In this code the program changes the fill colour for any object. I would want it to change it only for rectangles.

Thanks for the help.

Answer Source

Here are three common solutions to this problem:

Using the item type

You can ask the canvas for the type of the object:

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

Using tags

Another solution is to give each item one or more tags. You can then query the tags for the current item.

First, include one or more tags on the items you want to be clickable:

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

Next, check for the tags on the item you're curious about, and check to see if your tag is in the set of tags for that item:

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

Create bindings on tags

A third option is to attach the bindings to the tags rather than the canvas as a whole. When you do this, your function will only be called when you click on item with the given tag, eliminating the need to do any sort of runtime check:

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