http://www.perlmonks.org?node_id=1002091


in reply to How to destroy and re-create bound widgets

I ran your code, and saw one problem immediately.
#Here are some fake buttons using sub-canvas: my $scan1 = $rightframe-> Canvas(-width => 64, -height => 54, -highlig +htthickness => 0); my $scan2 = $rightframe-> Canvas(-width => 64, -height => 54, -highlig +htthickness => 0); my $scan3 = $rightframe-> Canvas(-width => 64, -height => 54, -highlig +htthickness => 0); &scan1start; MainLoop; sub reset { my @buttons = ($scan1,$scan2,$scan3); foreach (@buttons) { $_-> destroy; } #&scan1start; } sub scan1start { if ($numscan1 == 0) { $scan1-> form(-left => '187', -top => '319'); $scan1-> configure(-background => 'black'); $scan1-> Tk::bind('<Button-1>' => sub { .... etc .... etc .... etc }
You define $scan1, $scan2, $scan3 globally, then destroy them in your reset sub. Then without recreating them, you try to access them in &scan1start.

Although it dosn't address all your issues, you might start by tring something like this:

#!/usr/bin/perl use warnings; use Tk; use strict; my $mw = new MainWindow; $mw-> geometry('640x480'); $mw-> resizable( 0, 0 ); my $numscan1 = 0; my $numscan2 = 0; my $numscan3 = 0; my $leftframe = $mw-> Frame(); $leftframe->form(-left => '%0', -right => '%25', -bottom => '%99', -to +p => '%1'); my $resetb = $leftframe-> Button(-text => 'Reset', -command => \&reset + )->form(-left => '%50', -top => '%50'); my $rightframe = $mw-> Frame(-relief => 'groove', -borderwidth => 1); $rightframe-> form(-left => $leftframe, -right => '%99', -bottom => '% +99', -top => '%1'); my $maincanvas = $rightframe-> Canvas(-background => 'blue', -highligh +tthickness => 0); $maincanvas-> form(-left => '%1', -right => '%99', -bottom => '%99', - +top => '%1'); #Here are some fake buttons using sub-canvas: #my $scan1 = $rightframe-> Canvas(-width => 64, -height => 54, -highli +ghtthickness => 0); #my $scan2 = $rightframe-> Canvas(-width => 64, -height => 54, -highli +ghtthickness => 0); #my $scan3 = $rightframe-> Canvas(-width => 64, -height => 54, -highli +ghtthickness => 0); my $scan1; my $scan2; my $scan3; &scan1start; MainLoop; sub reset { my @buttons = ($scan1,$scan2,$scan3); foreach (@buttons) { $_-> destroy; } &scan1start; } sub scan1start { $scan1 = $rightframe-> Canvas(-width => 64, -height => 54, -highlight +thickness => 0); $scan2 = $rightframe-> Canvas(-width => 64, -height => 54, -highlight +thickness => 0); $scan3 = $rightframe-> Canvas(-width => 64, -height => 54, -highlight +thickness => 0); if ($numscan1 == 0) { $scan1-> form(-left => '187', -top => '319'); $scan1-> configure(-background => 'black'); $scan1-> Tk::bind('<Button-1>' => sub { $numscan1 = 1; &scan2start; &scan3start; &scan1start; } ); $scan1-> Tk::bind('<Button-3>' => sub { }); } elsif ($numscan1 == 1) { $scan1-> form(-left => '187', -top => '319'); $scan1-> configure(-background => 'white'); $scan1-> Tk::bind('<Button-3>' => sub { if (($numscan2 == 0) && ($numscan3 == 0)) { $scan2->formForget; $scan3->formForget; $numscan1 = 0; &scan1start; } } ); $scan1-> Tk::bind('<Button-1>' => sub { }); } } sub scan2start { if ($numscan2 == 0) { $scan2-> form(-left => '102', -top => '211'); $scan2-> configure(-background => 'black'); $scan2-> Tk::bind('<Button-1>' => sub { $numscan2 = 1; &scan2start; } ); $scan2-> Tk::bind('<Button-3>' => sub { }); } elsif ($numscan2 == 1) { $scan2-> form(-left => '102', -top => '211'); $scan2-> configure(-background => 'white'); $scan2-> Tk::bind('<Button-3>' => sub { $numscan2 = 0; &scan2start; } ); $scan2-> Tk::bind('<Button-1>' => sub { }); } } sub scan3start { if ($numscan3 == 0) { $scan3-> form(-left => '202', -top => '211'); $scan3-> configure(-background => 'black'); $scan3-> Tk::bind('<Button-1>' => sub { $numscan3 = 1; &scan3start; } ); $scan3-> Tk::bind('<Button-3>' => sub { }); } elsif ($numscan3 == 1) { $scan3-> form(-left => '202', -top => '211'); $scan3-> configure(-background => 'white'); $scan3-> Tk::bind('<Button-3>' => sub { $numscan3 = 0; &scan3start; } ); $scan3-> Tk::bind('<Button-1>' => sub { }); } }
P. S. I also notice that you have recursive subroutine called in scan1start(). The way I set it up in the example, or in any Tk script, a recursive widget-creating sub is bound to cause havoc. By the way, why are you not using the createWindow method to embed those sub canvases?

I'm not really a human, but I play one on earth.
Old Perl Programmer Haiku ................... flash japh

Replies are listed 'Best First'.
Re^2: How to destroy and re-create bound widgets
by Phinix (Acolyte) on Nov 05, 2012 at 01:40 UTC

    I did try createWindow... I'm still learning so I've been just experimenting and doing research trying to get the syntax right. Perhaps though you could explain why doing this:

    my $canvaswindow = $canvas->createWindow(0,0, -window => $widget); $canvaswindow->Tk::bind('<Button-1>' => sub { &dostuff0 });

    ...gives me an error saying: "Global symbol "$canvaswindow" requires explicit package name at line 3."

    I have created $widget before attempting this, of various types. Is it not possible to create custom event binds on canvas objects? If so, that is why I do not use createWindow. If it is possible I would love to know how.

    EDIT: I was able to get things working after I realized that the createWindow method isn't so much creating a new object that gets a reference but rather more like saying "put me here" to a previously created object template.

    So, the above instead becomes:

    $canvas->createWindow(0,0, -window => $widget); $widget->Tk::bind('<Button-1>' => sub { &dostuff0 });
    I'll post a full working example in a bit once I finish the translation. Thanks for all the helpful pointers and syntax examples though!
      It sounds like you, as a beginner, my want to reconsider your design. The first thing I have to say, is why do you need the overlapping secondary sub-canvases? If you can make something on your sub-canvas, you can do the same thing on the underlying canvas. You can still put a background image on the main canvas, then instead of overlaying other canvases, why not create rectangular regions on the base canvas? In any event, look at this example:
      #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = new MainWindow; my $main = $mw -> Scrolled("Canvas",-scrollbars=>'e')-> pack(-side =>'left', -fill => 'both', -expand => 1); my $canvas = $main->Subwidget("canvas"); Tk::bind($canvas, '<MouseWheel>', [ sub {$canvas->yview('scroll', -($_[1] / 120) * 3,'units')}, Ev('D')]); my $see = "\nHaaa, See that and scroll!"; my $info = $main->createText(180, 15, -text => "$see", -font => 'Arial 11 bold' , -fill => 'red'); $main->configure(-scrollregion => [0,0,2000 , 2000]); my $canvas_cube = $main->Canvas(-width => 45, -height => 45, -background => 'green'); my $canvasWindow = $main->createWindow(75,75, -window => $canvas_cube) +; Tk::bind( $canvas_cube, '<Enter>' => sub { print "Enter\n"; }); Tk::bind( $canvas_cube, '<Leave>' => sub { print "Leave\n"; }); Tk::bind( $canvas_cube, '<Button-1>' => sub { print "1\n"; }); $canvas->focus; MainLoop;

      I'm not really a human, but I play one on earth.
      Old Perl Programmer Haiku ................... flash japh