# Ruby/Tk - binding to canvas items

**URL:** <https://www.ruby-forum.com/t/ruby-tk-binding-to-canvas-items/125413>\
**Category:** Ruby\
**Created:** [January 8, 2008, 10:38pm UTC](https://www.ruby-forum.com/t/ruby-tk-binding-to-canvas-items/125413 "2008-01-08T22:38:30Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![viciu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/v/7ba0ec/32.png) [@viciu](https://www.ruby-forum.com/u/viciu)\
**Post date:** [January 8, 2008, 10:38pm UTC](https://www.ruby-forum.com/t/ruby-tk-binding-to-canvas-items/125413/1 "2008-01-08T22:38:30Z")

</div>

Hi!  
I have canvas items (TkcLine to be exact) and I need to bind some code  
executed on click. I use code similar to this:

line = TkcLine.new($root, arg, :fill =\> ‘#000’, :width =\> 2)  
line.bind(“Button-1”) {|e|  
#some actions  
}

It works, but I dont know how to get which item was clicked.

I have bunch of lines in one canvas. Event passed to code does refers  
only to widget which was clicked, but this is canvas itself, not  
particular canvas item. Is possible to know which line was clicked?

## Best regards,

Witold R.  
[nhw.pl](http://nhw.pl/wp/) (EN blog)  
[http://FriendsFeedMe.com](http://FriendsFeedMe.com)

---

<div class="post-metadata">

**Author:** ![viciu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/v/7ba0ec/32.png) [@viciu](https://www.ruby-forum.com/u/viciu)\
**Post date:** [January 9, 2008, 3:21am UTC](https://www.ruby-forum.com/t/ruby-tk-binding-to-canvas-items/125413/2 "2008-01-09T03:21:48Z")

</div>

Witold R. wrote:

> Hi!  
> I have canvas items (TkcLine to be exact) and I need to bind some code  
> executed on click. I use code similar to this:
> 
> line = TkcLine.new($root, arg, :fill =\> ‘#000’, :width =\> 2)  
> line.bind(“Button-1”) {|e|  
> #some actions  
> }
> 
> It works, but I dont know how to get which item was clicked.

I just tested that this works:

line.bind(“Button-1”) {|e|  
p line  
}

It’s a closure, so you can refer to local scope.

There’s one thing to watch out for:

line = TkcLine.new…  
line.bind(“Button-1”) {|e|  
p line  
}

line = TkcLine.new…  
line.bind(“Button-1”) {|e|  
p line  
}

This creates two lines, but the scopes share the same binding for the  
local var “line”, so the two blocks will both operate on the second  
line. Instead, use different var names, or use an #each loop.

---

<div class="post-metadata">

**Author:** ![viciu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/v/7ba0ec/32.png) [@viciu](https://www.ruby-forum.com/u/viciu)\
**Post date:** [January 9, 2008, 12:15pm UTC](https://www.ruby-forum.com/t/ruby-tk-binding-to-canvas-items/125413/3 "2008-01-09T12:15:44Z")

</div>

Joel VanderWerf wrote:

> This creates two lines, but the scopes share the same binding for the  
> local var “line”, so the two blocks will both operate on the second  
> line. Instead, use different var names, or use an #each loop.

Yeah, use of #each was required, since I was iterating through array and  
needed index of elements inside of handler.

Thank You.

---

<div class="post-metadata">

**Author:** ![viciu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/v/7ba0ec/32.png) [@viciu](https://www.ruby-forum.com/u/viciu)\
**Post date:** [January 9, 2008, 4:15pm UTC](https://www.ruby-forum.com/t/ruby-tk-binding-to-canvas-items/125413/4 "2008-01-09T16:15:10Z")

</div>

From: Witold R. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
Subject: Ruby/Tk - binding to canvas items  
Date: Wed, 9 Jan 2008 06:38:33 +0900  
Message-ID: [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

> I have bunch of lines in one canvas. Event passed to code does refers  
> only to widget which was clicked, but this is canvas itself, not  
> particular canvas item. Is possible to know which line was clicked?

## On Tcl/Tk’s canvas manual,

## The tag current is managed automatically by Tk; it applies to the current item, which is the topmost item whose drawn area covers the position of the mouse cursor. If the mouse is not in the canvas widget or is not over an item, then no item has the current tag.

So, you should use ‘current’ to denote the target item.  
Or use a TkcTagCurrent object.

## For example,

require ‘tk’  
c = TkCanvas.new.pack  
current = TkcTagCurrent.new(c)  
callback = proc{|w|  
p c  
p w  
p w.itemconfiginfo(‘current’)  
p current.configinfo  
p w.find\_withtag(‘current’)  
}

[100, 120, 140, 160, 180, 200].each{|y|  
TkcLine.new(c, [50, y], [200, y]).bind(‘1’, callback, ‘%W’)  
# or .bind(‘1’, ‘%W’, &callback)  
}  
Tk.mainloop
