Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

I am having difficulty attempting to destroy widgets I have bound to mouse click events. All the documentation I read seems to indicate the problem is likely related to internal tables maintained for destroyed widgets, however none seem to elaborate on how to clear them, or how to "detach" or "unbind" events from widgets so they may be safely destroyed and re-created from scratch.

The program I am writing reaches a point where it needs to delete all dynamically created "buttons" (widgets with mouse binds on them) and then re-create the first of them by invoking a sub-routine to basically start over. Below is a sample of the code, to show the basic concept

Basically what it does is set up the container structure, then invoke &scan1start; which is a subroutine to build the first fake widget button, and bind it to right and left mouse (not the reset button, leave that alone for now!) I am using canvas as the bind widget because I want to give it a background image without inheriting the functionality of a regular button.

Clicking this first fake widget button button runs the next two subroutines to create two more buttons (and also changes the first button's color). Clicking either of these new buttons will change their color, and right-clicking will change it back. Right-clicking the first button hides the two higher buttons, but only if they are "off" (black in this example.)

You can test all of this and it works fine, until you click the reset button. This button is supposed to destroy all the buttons, then run the initial subroutine to re-create the first button and set up it's initial bindings again, basically starting all over. However, as you can see perl complains about a bound event and the button is never re-created.
#!/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, -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 { $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 { }); } }

Sorry if this seems similar to another question I asked recently about canvas items, however that example was somewhat unclear and presented in a misleading context.

This is specifically an issue with unbinding/destroying bound widgets. I have attempted it with numerous other widget types (buttons, images), inside numerous container types and had the same result with all of them.

I know I am not the most well-versed in the language but this particular snag is really starting to recede my hairline!

EDIT: Just thought I would add, this same "command bound to event" error crops up when I attempt to use ->delete('all') and formForget instead of destroy. Very very frustrating.


In reply to How to destroy and re-create bound widgets by Phinix

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (5)
As of 2024-04-19 09:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found