Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

Using the following code, if I open the dropdown and close it by clicking either the down-arrow or the entry box to the left of the down arrow, everything is fine.

But if I select an item, or click elsewhere to close the dropdown, the 'after' timer keeps going and I get the error below when I close the app.

I'm not using Tkx::MainLoop() because this is a conversion from a console app to a GUI app that does stuff in the background.

My question is: What is the timer doing, and how do I stop it and/or avoid getting the error? I could call Tkx::after_cancel(Tkx::after_info()); right before Tkx::update, but that would cancel all timers.

Thanks.

Perl code:
#!/usr/bin/perl -w use strict; use Tkx; my $mw = Tkx::widget->new('.'); my $combo = $mw->new_ttk__combobox(-values=>['item1', 'item2', 'item3' +]); $combo->g_pack(); while (eval{Tkx::winfo_exists('.')}) { Tkx::update(); my $after = Tkx::after_info(); if ($after) { my $info = Tkx::after_info($after); print ">>> $after // $info\n"; # to see the timer go } }
Error:
can't invoke "winfo" command: application has been destroyed while executing "winfo exists $w" (procedure "ttk::entry::AutoScroll" line 3) invoked from within "ttk::entry::AutoScroll .c" (in namespace inscope "::" script line 1) invoked from within "::namespace inscope :: {ttk::entry::AutoScroll .c}" ("uplevel" body line 1) invoked from within "uplevel #0 $Repeat(script)" (procedure "ttk::Repeat" line 3) invoked from within "ttk::Repeat" ("after" script)
Perl version (stock latest ActivePerl 5.10.0 build 1004, but same since at least 5.10.0/1002):
C:\>perl --version This is perl, v5.10.0 built for MSWin32-x86-multi-thread (with 5 registered patches, see perl -V for more detail) Copyright 1987-2007, Larry Wall Binary build 1004 [287188] provided by ActiveState http://www.ActiveSt +ate.com Built Sep 3 2008 13:16:37 Perl may be copied only under the terms of either the Artistic License + or the GNU General Public License, which may be found in the Perl 5 source ki +t. Complete documentation for Perl, including FAQ lists, should be found +on this system using "man perl" or "perldoc perl". If you have access to + the Internet, point your browser at http://www.perl.org/, the Perl Home Pa +ge.

Replies are listed 'Best First'.
Re: Tkx combobox error on quit
by zentara (Cardinal) on Sep 22, 2008 at 18:41 UTC
    Hi, here is a Tk version of what I think you want. I have no idea what Tkx does, but the idea should be the same.
    #!/usr/bin/perl -w use strict; use Tk qw/tkinit DoOneEvent exit DONT_WAIT ALL_EVENTS/; use Tk::JComboBox; my $mw = MainWindow->new(); my $combo = $mw->JComboBox( -choices => [ { -name => 'Black', -value => 1 }, { -name => 'Blue', -value => 2 }, { -name => 'Green', -value => 3 }, { -name => 'Purple', -value => 4 }, 'Red', { -name => 'Yellow', -value => 5 } ] )->pack; my $count = 0; my $timer = $mw->repeat(1000,sub{ $count++; }); while ( Tk::Exists($mw) ) { $mw->DoOneEvent( DONT_WAIT | ALL_EVENTS ); print "$count\n"; if( $count > 10 ){ $mw->destroy } } print "end of gui, press a key to continue\n"; <>; print "exiting\n";

    I'm not really a human, but I play one on earth Remember How Lucky You Are

      Hi.

      In Tkx, there's Tkx::i::DoOneEvent(), which I also tried, but it's horribly slow (I believe it does literally ONE event each time it's called). Is there a Tkx equivalent of ( DONT_WAIT | ALL_EVENTS )? That looks like it would do what I need, but I've been unsuccessful with the Google on that one. Tkx.pm passes all arguments of DoOneEvent to Tcl/Tk, and I've tried all sorts of ways of putting ( DONT_WAIT | ALL_EVENTS ) in there without success.

      Thanks.

Re: Tkx combobox error on quit
by zentara (Cardinal) on Sep 22, 2008 at 18:16 UTC
    I'm not using Tkx::MainLoop() because this is a conversion from a console app to a GUI app that does stuff in the background.My question is: What is the timer doing,

    I don't have Tkx, and can't run your code, but you need to understand what an eventloop is. When you call MainLoop, you start the eventloop and the widgets work. What is probably happening is you are starting the after timer, then since you never start the MainLoop, there is no eventloop for it to run in.

    I can't run your code, but you might try this, which is a manual MainLoop, at the end of your code, or put it in your while loop

    while (1) { $mw->DoOneEvent( DONT_WAIT | ALL_EVENTS ); }

    But if you are converting from a console app to a gui, and need to keep things going in the background, there are much better ways than what you are trying. Post exactly what type of console app it is, what is does, and what kind of a gui you need for it. Usually a piped open, fork, or threads will work fine.

    But Perl will let you do things the hard way if you want. :-)


    I'm not really a human, but I play one on earth Remember How Lucky You Are

      Yes, I know what an eventloop is, but I have background stuff going on in addition to making widgets work. Calling Tkx::update() was one way to keep widgets working in my manual MainLoop, and Tkx::i::DoOneEvent was another way. DoOneEvent is way too slow; it seems like it does ONE event each time it's called, and with the background stuff, the GUI is quite unresponsive.

      The main problem is that I am not starting the timer. Tkx or Tcl/Tk (since Tkx is supposed to be just a wrapper for this) is starting it when the dropdown opens, and fails to stop it if the dropdown is closed in a way other than by clicking the down arrow or clicking in the entry field directly beside the down arrow.

      I guess my question is how to stop that timer automatically. Or how to determine the timer number associated with that dropdown so I can manually cancel it with Tkx::after_cancel().

      Tkx::i::DoOneEvent( DONT_WAIT | ALL_EVENTS ); looks like it could do what I need, but unfortunately I have been unable to Google how to get it to recognize ( DONT_WAIT | ALL_EVENTS ), or what their Tkx equivalent is.

Re: Tkx combobox error on quit
by zentara (Cardinal) on Sep 22, 2008 at 20:57 UTC
    I know what an eventloop is, but I have background stuff going on in addition to making widgets work.

    Widgets won't work right if you have background stuff going at the same time, unless your background stuff is forked or threaded. The execution pointer can only be at one place at a time in a process, and eventloop widgets won't work unless that eventloop is in control. Now there are exceptions to this. If in your while loop, you do DoOneEvent, and also run simple things like increments or file reads, you can keep things responsive. But if you try to run backticks or system on commands, or slow db accesses, it will make the gui unresponsive.

    The best thing is to tell us what you are trying to do in the background.

    As far as the DoOneEvent being slow, did you run my Tk version? I get very rapid response, where the digits 1 to 10 are repeatedly printed each second.


    I'm not really a human, but I play one on earth Remember How Lucky You Are