Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Why does widget->destroy give the error Tk::Error widget was deleted before its visibility changed?

by thomas.bystrom (Novice)
on Apr 17, 2015 at 09:42 UTC ( #1123733=perlquestion: print w/replies, xml ) Need Help??
thomas.bystrom has asked for the wisdom of the Perl Monks concerning the following question:

Hello!

When running the example below I get the error:

Tk::Error: window ".toplevel.frame1.hlist.menu" was deleted before its + visibility changed at C:/Dwimperl/perl/site/lib/Tk/Widget.pm line 10 +00. Tk callback for tkwait <Button-1> (command bound to event)
Example.

#!/usr/bin/perl -w use strict; use Tk; use Tk::Pane; use Tk::HList; sub door { my $house = shift; my $door_W = $house->Toplevel(); my $hlist = $door_W->Scrolled( 'HList', -scrollbars => "se", -columns => 1, -header => 1, )->pack( -expand => 1, -fill => 'both'); $hlist->headerCreate(0, -text => 'Title'); $hlist->columnWidth(0, ''); $hlist->bind("<Button-1>" => [\&knock_on_door, $door_W]); my $exit_B = $door_W->Button( -text => 'Exit', -command => sub { $door_W->destroy(); }, -relief => 'raised', )->pack(-side => 'left'); } sub knock_on_door { my $frame = shift; my $pop_menu = $frame->Menu( -menuitems => [ ['command', 'Knock on door.', -command => sub { print "Knock! Knock!!!\n"; } ], '', ] )->Popup(-popover => "cursor", -popanchor => 'nw'); $pop_menu->destroy; } my $mw = MainWindow->new; $mw->Button(-text => "Close", -command =>sub{exit})->pack(); door($mw); MainLoop;

You receive the error after selecting "knock on door" and pushing the Exit button.
You don't recieve the error if you only push the Exit button.
I am running TK 804.032

Thankful for any ideas.

Thomas

  • Comment on Why does widget->destroy give the error Tk::Error widget was deleted before its visibility changed?
  • Select or Download Code

Replies are listed 'Best First'.
Re: Why does widget->destroy give the error Tk::Error widget was deleted before its visibility changed?
by Anonymous Monk on Apr 17, 2015 at 09:54 UTC

    Where did you get this sample?

    Tk::Error: window ".toplevel.frame1.hlist.menu" was deleted before its visibility changed ... You don't recieve the error if you only push the Exit button.

    That is because no Menu object is created, and then destroyed before it could be displayed.

    sub knock_on_door always creates a new menu in $popup_menu, and that variable always goes out of scope and is supposed to be destroyed, but Tk does you a favor and keeps it around because its knows you're not Coping with Scoping

    Make sense?

    If you make it a global and the only one, then you won't get that message

    #~ my $pop_menu = $frame->Menu( -menuitems => our $pop_menu ; $pop_menu ||= $frame->Menu( -menuitems =>

    But that isn't good practice, see tips at Re^3: Perl Tk Multiple Notebook Editing and Save (life cycle of variables) and the links it links

      Thanks!

      Your response pushed me forward.
      I did'nt solve the problem with making the pop_menu global.
      My solution is to withdraw the widget, because I want to reuse it later in my script (10 000 rows in 8 pm files).

      Thanks again for your Quick response.

        I am facing the same problem in several places in my application where I am using a menu bound to an hlist.

        I do not understand the proposed solution and how scoping plays a part

        In my application I am assigning the menu object to a hash element so that I can refer to it and try to destroy it when the window is going to close. like this:

        $winInfoRef->{MENU}= $winInfoRef->{HLIST}->Menu(-tearoff=>1,

        I have recreated the problem with the originally posted example code, I changed the lines to make $pop_menu a global as suggested (and relisted below)

        #~ my $pop_menu = $frame->Menu( -menuitems => our $pop_menu ; $pop_menu ||= $frame->Menu( -menuitems =>

        but I still get the same error:

        Tk::Error: window ".toplevel.frame.hlist.menu" was deleted before its +visibility changed at C:/Perl/site/lib/Tk/Widget.pm line 1000. Tk callback for tkwait <Button-1> (command bound to event)

        Thomas said he withdrew his menu, but I tried that too with no success(maybe I don't know how) Can anyone share more insight into this error?

Re: Why does widget->destroy give the error Tk::Error widget was deleted before its visibility changed?
by Anonymous Monk on Jun 12, 2017 at 05:55 UTC

    This is a down right antique bug ... reported years later in Bug #28238 for Tk: Tk::Menu->Popup never returns (Win32)

    Workaround that makes sense to me is this , it will work on win32 as expected, and should work pretty much anywhere Tk does

    Popup($pop_menu,-popover => "cursor", -popanchor => 'nw'); .... sub Popup { package Tk::Wm; my $w = shift; $w->configure(@_) if @_; $w->idletasks; my ($mw,$mh) = ($w->reqwidth,$w->reqheight); my ($rx,$ry,$rw,$rh) = (0,0,0,0); my $base = $w->cget('-popover'); my $outside = 0; if (defined $base) { if ($base eq 'cursor') { ($rx,$ry) = $w->pointerxy; } else { $rx = $base->rootx; $ry = $base->rooty; $rw = $base->Width; $rh = $base->Height; } } else { my $sc = ($w->parent) ? $w->parent->toplevel : $w; $rx = -$sc->vrootx; $ry = -$sc->vrooty; $rw = $w->screenwidth; $rh = $w->screenheight; } my ($X,$Y) = AnchorAdjust($w->cget('-overanchor'),$rx,$ry,$rw,$rh); ($X,$Y) = AnchorAdjust($w->cget('-popanchor'),$X,$Y,-$mw,-$mh); # adjust to not cross screen borders if ($X < 0) { $X = 0 } if ($Y < 0) { $Y = 0 } if ($mw > $w->screenwidth) { $X = 0 } if ($mh > $w->screenheight) { $Y = 0 } $w->Post($X,$Y); #~ $w->waitVisibility; ## Bug #28238 for Tk: Tk::Menu->Popup never re +turns (Win32) $w->update; }

      Thanks! I had read over the bug report, but couldn't figure out how to apply it in my situation. I am not directly posting the popup, it is bound to the button-3 callback event...

      $winInfoRef->{HLIST}->bind('<Button-3>' => sub{$winInfoRef->{MENU}->Po +pup(-popover=>'cursor',-popanchor=>'ne')}

      so I think the suggested workaround is to add your Popup Subroutine and change my bind to this?

      $winInfoRef->{HLIST}->bind('<Button-3>' => sub{Popup($winInfoRef->{MEN +U},-popover=>'cursor',-popanchor=>'ne')}

      Forgive my weak OO knowledge... Does adding the code for the Popup subroutine replace the Tk Popup routine ?

        Thank You! This worked a charm for me... Since I was using popup menus in more than one place, I included the code from the kind Anonymous Monk (it is copied so it can be downloaded below) in a file called MenuPopup.pm, and added:

        require MenuPopup;
        in my top level code

        In the bind method for my popup menu, I used:

        $winInfoRef->{HLIST}->bind('<Button-3>' => sub{ MenuPopup($winInfoRef->{MENU}, -popover=>"cursor",-popanchor=>'ne') });

        I thought I would be able to use:

        $winInfoRef->{HLIST}->bind('<Button-3>' => sub{ $winInfoRef->{MENU}->MenuPopup( -popover=>"cursor",-popanchor=>'ne'); });
        But I got an error saying the Tk::MenuPopup could not be found (I'm sure there would be a way to fix that, but I spent a lot of time getting to this solution and I've got to move on)

        Here is the code with some comments to help me remember how to use it:

        #Note this can be used to in place of the Popup Method found in TK/Wm. +pm # #it fixes a problem where if you ever used a popup menu, and then clos +ed the main #window that posted the menu, you would get a TK error saying somethin +g like: # Tk::Error: window ".toplevel.frame.hlist.menu" was deleted before + its visibility changed at # C:/Perl/site/lib/Tk/Widget.pm line 1000. # Tk callback for tkwait # It doesn't allow you to directly use as a method like $wid->MenuPopu +p(-opt1=>'opt',-opt2=>'blah'), # instead you call it and pass it the widget like this: MenuPopup($wid +,-opt1=>'opt',-opt2=>'blah); # When you use bind to enable the popup, use it like this: # $widget->bind('<Button-3>' => sub{ # MenuPopup($winInfoRef->{MENU},-popover=>"cursor", +-popanchor=>'ne'); # } # ); #The fix was commenting out #$w->waitVisibility; ## Bug #28238 for Tk: Tk::Menu->Popup never retur +ns (Win32) #I got this gem from the perlMonks after reaching out on http://www.pe +rlmonks.org/?node_id=1123733 sub MenuPopup { package Tk::Wm; my $w = shift; $w->configure(@_) if @_; $w->idletasks; my ($mw,$mh) = ($w->reqwidth,$w->reqheight); my ($rx,$ry,$rw,$rh) = (0,0,0,0); my $base = $w->cget('-popover'); my $outside = 0; if (defined $base) { if ($base eq 'cursor') { ($rx,$ry) = $w->pointerxy; } else { $rx = $base->rootx; $ry = $base->rooty; $rw = $base->Width; $rh = $base->Height; } } else { my $sc = ($w->parent) ? $w->parent->toplevel : $w; $rx = -$sc->vrootx; $ry = -$sc->vrooty; $rw = $w->screenwidth; $rh = $w->screenheight; } my ($X,$Y) = AnchorAdjust($w->cget('-overanchor'),$rx,$ry,$rw,$rh); ($X,$Y) = AnchorAdjust($w->cget('-popanchor'),$X,$Y,-$mw,-$mh); # adjust to not cross screen borders if ($X < 0) { $X = 0 } if ($Y < 0) { $Y = 0 } if ($mw > $w->screenwidth) { $X = 0 } if ($mh > $w->screenheight) { $Y = 0 } $w->Post($X,$Y); #$w->waitVisibility; ## Bug #28238 for Tk: Tk::Menu->Popup never ret +urns (Win32) $w->update; } #needed for require return 1;

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1123733]
Approved by kevbot
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (3)
As of 2017-10-20 09:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My fridge is mostly full of:

















    Results (260 votes). Check out past polls.

    Notices?