Morton Goldberg
9/5/2006 11:43:00 AM
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?
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.
Regards, Morton
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
#
# 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>