Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the tag of a shape when clicked

Lets say I have created a canvas in a Tkinter app.

In the canvas, I have drawn several rectangles.

What I want in essence, is to know in which rectangle the user has clicked, that is my main concern, but this is what I have tried and what I think might be the solution.

This is my layout:

for x in range(1,6):
        for y in range(1,7):     
            tableNumber = y + 6*(x-1)
            w.create_rectangle((table.xSeparation + table.width) * y - table.width,
                               (table.ySeparation + table.height) * x -  table.height,
                               (table.xSeparation + table.width)*y,
                               (table.ySeparation + table.height) * x,

                               fill="brown", tags="table" + str(tableNumber))

            w.tag_bind("table" + str(tableNumber), '<Button-1>', do)

So this just creates rectangles in a rows and columns layout.

Each rectangle has a specific tag in the form of table1,table2 to table30.

When I click on the rectangle, the do function executes.

Let's say do was something like:

def do(event):
    print "click"

Not I get a "click" in the console for every click in the rectangle.

I would like to be able to get the tag of the clicked rectangle to be able to do something like this:

def do(event):
    print str(theTagOfTheClickedRectangle)

So I checked on what events I can call which are:

  • widget
  • x, y
  • x_root, y_root
  • char
  • keysym
  • keycode
  • num
  • width, height
  • type

None of the seem to pin point what rectangle I have clicked.

I thought about adding more parameters to the do function here:

w.tag_bind("table" + str(tableNumber), '<Button-1>', do(event, tag))

But that doesn't seem to work fine, but maybe I'm not doing the do right:

do(event, tag): #this doesn't work at all!!
    print event.x
    print tag

I hope the question is clear, if I got the tag in the same manner as I can get the 'x' and 'y' of the event, that would be very comfortable.

The only actual solution I can now think of, is working out the math of 'event.x' and 'event.y' and calculate, based on the coordinates of the click, on which rectangle the user has clicked, this seems overcomplicated for what I'm trying to do, though I've done it before and it obviously works.

I hope the question is clear, other wise please ask for any clarification.

Note that I'm not tied to any of this code, rather, I'm looking for a solution for this problem, the most efficient will work even if means not working with tags, or another type of widget or whatever is the easier.

like image 409
Trufa Avatar asked Dec 16 '22 08:12

Trufa


2 Answers

You can use something like this to reference the clicked-on object:

event.widget.find_withtag("current")

The tag "current" is special and represents the top-most object under the mouse.

like image 153
Bryan Oakley Avatar answered Jan 04 '23 02:01

Bryan Oakley


w.tag_bind("table" + str(tableNumber), '<Button-1>', do(event, tag))

should be changed to

tag = "table" + str(tableNumber)
callback = lambda event, tag=tag: do(event, tag)
w.tag_bind(tag, '<Button-1>', callback)

The lambda creates a function with the tag name as the default value of the second argument. Tkinter calls that function with just one argument, the event, and the second argument uses the default value.

like image 33
Steven Rumbalski Avatar answered Jan 04 '23 02:01

Steven Rumbalski