I tried running your code on my system which is OS X 10.4.7 running Ruby 1.8.2, and I don't see what you report. What I see is following:
* Right-clicking away from the the rectangle, the canvas' contextual menu pops-up.
* Right-clicking on the rectangle.
** The rectangle's contextual menu pops-up.
** When the rectangle's menu is dismissed, the canvas' contextual menu pops-up.
With a small tweak, I was able to keep the canvas' contextual menu from popping up when the the rectangle is right-clicked. So what I have now running on my system works as you expected.
P.S. Just in case you want to compare what I am running with your own code.
<code>
#! /usr/bin/ruby -w
# Date: September 5, 2006
···
On Sep 3, 2006, at 10:40 AM, Josef Wolf wrote:
Hello!
I am trying to bind context-menus to a Tk canvas. The canvas itself should
have a context menu, giving the ability to create new objects. In addition,
every object should have its own context menu so that the object can be
modified/deleted. This is what I'm doing:
#! /usr/bin/ruby
require 'tk'
$-w = 1
root = TkRoot.new
canvas = TkCanvas.new.pack
# This is the context menu for the canvas to create new objects
#
menu=TkMenu.new
menu.add('command', 'label'=>'New Foo', 'command'=>proc{p "new foo"})
menu.add('command', 'label'=>'New Bar', 'command'=>proc{p "new bar"})
# canvas binding
canvas.bind("Button-3") { |e| evt=e; menu.popup(e.x_root, e.y_root) }
# Now create a new object and bind to it a context menu to modify/delete
# the object
#
rect = TkcRectangle.new(canvas, 0, 0, 50, 50, "fill"=>"white")
menu=TkMenu.new
menu.add('command', 'label'=>'Edit', 'command'=>proc{p "edit"})
menu.add('command', 'label'=>'Delete', 'command'=>proc{p "del"})
# object binding
canvas.itembind(rect, "Button-3") { |e| menu.popup(e.x_root, e.y_root) }
Tk.mainloop
Unfortunately, this don't work as desired. As soon as the binding to the
object is done, the canvas binding seems to be overridden. Even when
right-klicking on empty space in the canvas, the object's menu is invoked.
Any ideas what I am doing wrong here?
#
# Contextual menus on a canvas
require 'tk'
DEBUG =
RIGHT_BUTTON = "Button-2" # On OS X right button is Button-2.
begin
root = TkRoot.new {title 'Ruby Tk'}
canvas = TkCanvas.new.pack
handled_by_rect = false
# This is the context menu for the canvas to create new objects
menu1=TkMenu.new
menu1.add('command', 'label'=>'New Foo', 'command'=>proc{p "new foo"})
menu1.add('command', 'label'=>'New Bar', 'command'=>proc{p "new bar"})
# Canvas binding
canvas.bind(RIGHT_BUTTON) do |e|
if handled_by_rect
handled_by_rect = false
else
menu1.popup(e.x_root, e.y_root)
end
end
# Now create a new object and bind to it a context menu to modify/delete
# the object
rect = TkcRectangle.new(canvas, 50, 50, 100, 100, "fill"=>"white")
menu2=TkMenu.new
menu2.add('command', 'label'=>'Edit', 'command'=>proc{p "edit"})
menu2.add('command', 'label'=>'Delete', 'command'=>proc{p "del"})
# Rectangle binding
canvas.itembind(rect, RIGHT_BUTTON) do |e|
menu2.popup(e.x_root, e.y_root)
handled_by_rect = true
end
# Set initial window geometry; i.e., size and placement.
win_w, win_h = 300, 200
# root.minsize(win_w, win_h)
win_lf = (root.winfo_screenwidth - win_w) / 2
root.geometry("#{win_w}x#{win_h}+#{win_lf}+50")
# Make Cmnd+Q work as expected on OS X.
root.bind('Command-q') {Tk.root.destroy}
Tk.mainloop
ensure
puts DEBUG unless DEBUG.empty?
end
</code>