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

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; }
  • Comment on Re: Why does widget->destroy give the error Tk::Error widget was deleted before its visibility changed?
  • Download Code

Replies are listed 'Best First'.
Re^2: Why does widget->destroy give the error Tk::Error widget was deleted before its visibility changed?
by boleary (Scribe) on Jun 12, 2017 at 12:51 UTC

    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;