Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re^2: Term::ReadLine and Tk

by zentara (Archbishop)
on Mar 16, 2008 at 13:41 UTC ( [id://674457]=note: print w/replies, xml ) Need Help??


in reply to Re: Term::ReadLine and Tk
in thread Term::ReadLine and Tk - Solved

That's cool to know, I've added it to my snippet collection. By the way, you can usually run 2 (or more) event-loop systems simultaneously, by having the master loop run a timer( at a fast interval ) to do a 1-loop update of all the slave loops.
#!/usr/bin/perl -w use strict; use Gtk2; use Tk; my $mw = MainWindow->new(-title=>'Tk Window'); Gtk2->init; my $window = Gtk2::Window->new('toplevel'); $window->set_title('Gtk2 Window'); my $glabel = Gtk2::Label->new("This is a Gtk2 Label"); $window->add($glabel); $window->show_all; my $tktimer = $mw->repeat(10, sub{ # do one loop in Gtk2 Gtk2->main_iteration while Gtk2->events_pending; }); $mw->Button(-text=>' Quit ', -command => sub{exit} )->pack(); MainLoop;

and more info than you probably care to know (which are my notes about the Tk event-loop collected over time)

The event loop is activated once the Perl/Tk programs MainLoop statement is reached. From that point in time onwards, MainLoop controls our program. As events happen, MainLoop dispatches them to a handler (a callback) for processing, and puts the application to sleep + for a short amount of time when the event queue is empty. This repeats + until there are no more events from any of the programs MainWindows, at which time MainLoop returns. Any code after the MainLoop statement is then executed. Here is the salient portion of the actual MainLoop subroutine from the + Perl/Tk source distribution: use Tk :eventtypes; while (Tk::MainWindow->Count) { DoOneEvent(ALL_EVENTS); } As you see, the Tk main loop processes all events, one by one, un +til the count of MainWindows becomes zero. The use tag :eventtypes im +ports various symbols used by DoOneEvent, the subroutine that actually dispatches individual events. For now its sufficient to know tha +t the subroutine expects one argument, a bit pattern, specifying what t +ypes of events to process, and whether to return immediately if there +are no such events, or to wait. The symbol ALL_EVENTS is the inclusive OR of all the various even +t types. The individual event types that DoOneEvent recognizes are: WINDOW_EVENTS include things such as keyboard entry, button clicks and window s +ize and visibility changes. FILE_EVENTS deal with reading and writing files and network sockets. TIMER_EVENTS are created by the after and repeat commands. IDLE_EVENTS are low priority callbacks only executed after all events of the previous types have been processed. The most common idle events a +re those that redraw widgets and refresh the display. You can queue +idle callbacks using DoWhenIdle. The :eventtypes tag defines one other symbol, DONT_WAIT, that can + be inclusively ORed with a DoOneEvent bit pattern to make the subrou +tine call non-blocking. Notice that MainLoop does not include DONT_WAI +T in its DoOneEvent bit pattern, meaning that DoOneEvent sleeps when t +here is nothing to do, instead of returning to MainLoop. This is actua +lly a good thing, as it allows other programs running on our computer a + slice of the CPU pie. MainLoops job is to dispatch events to callbacks in a timely fash +ion. As you write callbacks, keep in mind you are in a mutually cooper +ative environment all callbacks should be brief and non-blocking so th +e application remains responsive. ################################################################### > IDLE_EVENTS > are low priority callbacks only executed after all events of the > previous types have been processed. The most common idle events are > those that redraw widgets and refresh the display. You can queue idl +e > callbacks using DoWhenIdle. ################################################################### > Is there a way to selectively update() a certain widget and not > others? No, this is not possible. See also Message-Id: <87sn21mesh.fsf@vran.herceg.de> (in the comp.lang.tcl newsgroup) with a suggestion for a new "display" command for the Canvas widget. Unfortunately, DisplayCanvas is a static method so you can't already use Inline::C or XS to call this function. > I > have an application which is plotting a density map on a canvas, usi +ng > thousands of little rectangles. I also have a ProgressBar that I wou +ld > like to show me the plotting progress. If I call $progressbar->updat +e then > the whole window gets updated, including the canvas, which slows dow +n the > execution. Ideally, I would like the progressbar to update only, and + then > for the canvas to update only when all the plotting is done. > > Is this possible? > > It would be nice if the Canvas had a hidden buffer which we draw to, + and > then blit everything in one shot once we're done drawing ... hmmm .. +. > My solution for this problem is to unpack the canvas, do all the updating along with progressbar changes, and finally re-pack the canvas. ################################################################### >> use Tk :eventtypes; >> >> while (Tk::MainWindow->Count) { >> DoOneEvent(ALL_EVENTS); >> } > ################################################################### Just for kicks, I modified my code such that all the canvas items are hidden (using the brand new, oh-so-useful -state option) as I'm plotti +ng everything to my canvas, and changed back to normal only when everything is done. Doing that, only the progressbar got updated as I wanted, and the execution time was considerably shorter. ################################################################### #for fastest processing sub MainLoop { my ($self) = @_; unless ($Tk::inMainLoop) { local $Tk::inMainLoop = 1; while (Tk::MainWindow->Count) { DoOneEvent(Tk::DONT_WAIT()); my $job=shift(@{$self->{WorkQue}}); if(defined $job){ my($cmd,@args) = @$job; &{$cmd}(@args); } } } } } ####################################################### For an event primer please refer to The Perl Journal #3 (Volume 1, Iss +ue 3, Fall 1996), Events and Other Things. (Old, but not dated). A large (in progress) + chapter titled Anontomy of the MainLoop will bring things up-to-date. This is a diff +icult arena to come to grasp with, but, essentially, as Marc noted, MainLoop{} looks +like this: while (we have 1 or more MainWindows active) { DoOneEvent(but don't block) } DoOneEvent() looks for events in the various Tk event queues and e +xecutes them - events are things like button clicks, timers, file I/O, etcetera. There +are also low-priority idle events handled after all the important events are cleared. > I just did a little experiment, and I think this will set you > in the right direction: > > use strict; > use Tk qw/tkinit DoOneEvent exit DONT_WAIT ALL_EVENTS/; You can also do: use Tk qw/:eventtypes/; to import all the good event stuff, including these event "bit ma +sks", which can be inclusively ORed together to specify what events to +process. DONT_WAIT return immediately if no events - DO NOT BLO +CK WINDOW_EVENTS X11 keyboard/mouse events FILE_EVENTS file I/O events TIMER_EVENTS repeat/after, etc. IDLE_EVENTS low priority events ALL_EVENTS all of the above Quoting the Pocket Ref: When passed ALL_EVENTS DoOneEvent() processes events as they arise, and puts the application to sleep when no further events a +re outstanding. It first looks for an X or I/O event and, if found, calls the handler and returns. If there is no X or I/O event, it + looks for a single timer event, invokes the callback, and returns. If no X, +I/O or timer event is ready, all pending idle callbacks are executed, if any. + In all cases DoOneEvent() returns 1. When passed DONT_WAIT, DoOneEvent() work +s as above except that it returns immediately with a value of 0 if there are + no events to process. > > my $mw = tkinit; > $mw->Button( > -text => 'Test', > -command => sub {print "Pushed\n"}, > )->pack(); > $mw->Button( > -text => 'Quit', > -command => sub {Tk::exit(0)}, > )->pack(); > > my $I; > while (1) { > $mw->DoOneEvent(DONT_WAIT|ALL_EVENTS); > if (++$I > 1000) { > print '.'; > $I = 0; > } > } > > -- > Marc Dashevsky (remove "_" from address to reply by e-mail) So, for X10 home automation programming, you need two basic ingre +dients: 1) a non-blocking way to process X10 events. So, basically, be a +ble to send an all-lights-on w/o blocking, or poll (w/o blocking) to det +ermine if A10 in On or off (e.g.). 2) a non-blocking way to process perl/Tk events - DoOneEvent. So +mething like this: while (my $stat = $mw->DoOneEvent( DONT_WAIT | ALL_EVENTS )){} sprinkled throughout your code might work, but that's just really thi +s in disguise: $mw->update; You can balance which events get priority by using an event mask, bu +t make sure you process idle event occasionally else the display will never upda +ted. So your "mainloop" might be: while ( 1 ) { &process_x10_event; $mw->DoOneEvent(blah); # or simply $mw->update() might suffice } You should check out the X10 codes on CPAN, as well as (I think) Mist +er House, which, when I discovered it, caused me to drop my Perk/Tk X10 project becaus +e it was so good!

I'm not really a human, but I play one on earth. Cogito ergo sum a bum

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://674457]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (7)
As of 2024-03-28 22:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found