Using bind with a Canvas

When you try to use the bind method with a Canvas widget, you can easily run into unexpected problems. You may either get an error and your script won’t run, or your script will run but your bind won’t seem to have any effect. What’s happening here is that Canvas objects have their own special bind method that works with tags and item IDs. To get around this, you’ll need to use CanvasBind, a special method that binds events to the canvas as a whole:

$canvas = $mw->Canvas(  );
$canvas->CanvasBind("<Button-1>", sub { print "bind!\n"; });

If you used the Scrolled method to create your Canvas, you’ll have an added difficulty; you’ll have to use the Subwidget method to get to the Canvas widget:

$canvas = $mw->Scrolled("Canvas");
$real_canvas = $canvas->Subwidget("canvas");
$real_canvas->CanvasBind("<Button-1>", sub { print "bind!\n" });

Other than this one small annoyance, bind works just as you would expect. This example prints the Canvas coordinate you clicked on:

$c = $mw->Scrolled("Canvas")->pack(  );
$canvas = $c->Subwidget("canvas");
$canvas->CanvasBind("<Button-1>", [ \&print_xy, Ev('x'), Ev('y') ]);
sub print_xy {
  my ($canv, $x, $y) = @_;
  print "(x,y) = ", $canv->canvasx($x), ", ", $canv->canvasy($y), "\n";
}

To summarize, use bind to create event bindings to Canvas items, and use CanvasBind to create event bindings to the Canvas widget.

Get Mastering Perl/Tk now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.