From: Brian F. <bfr...@gm...> - 2007-07-31 02:16:51
|
All, I found the threads example posted in this group and began playing around. I've modified the code to add a splash screen using Win32::GUI:SplashScreen, a timer taken from Tutorial_Part4_timer.pl, a statusbar, and a notifyicon. For some reason the timer never gets fired. I've tried removing the splashscreen and threads but it still won't fire. The tutorial works ... why doesn't this: #!/perl -w use strict; use warnings; $|=1; use Win32::GUI; use Win32::GUI::SplashScreen; use threads; use threads::shared; use Thread::Queue; ## Create worker threads and associated variables. ## -- THIS MUST BE DONE, AND ALL THREADS STARTED ## -- BEFORE THE WINDOW IS CREATED. my $TQ1 = new Thread::Queue; my $TQ2 = new Thread::Queue; my $ts1_run : shared = 0; my $ts2_run : shared = 0; my $t1_objHandle : shared = 0; my $t2_objHandle : shared = 0; my $thread1 = threads->new(\&Thread1); my $thread2 = threads->new(\&Thread2); ## Hide Perl Window my $perlW = Win32::GUI::GetPerlWindow(); #Win32::GUI::Hide($perlW); # Create and diaplay the splash screen Win32::GUI::SplashScreen::Show( -file => "splash.bmp", # set a name that doe not exist to force internal splash screen -mintime => 3, ); # Hide the splash - blocks until the splashscreen is removed Win32::GUI::SplashScreen::Done(); ## Create Window my $win = new Win32::GUI::Window( -name => 'winMain', -title => "My Main Window", -size => [700, 500], -onResize => \&resizeWin, ); my $t1 = $win->AddTimer('T1', 1000); # never calls sub T1_Timer $win->AddButton( -name => 'btnRun1', -size => [50,20], -pos => [4,10], -text => 'Run 1', ); $win->AddProgressBar( -name => 'pbT1', -size => [120,20], -pos => [58,10], -smooth => 1, ); $win->{pbT1}->SetRange(0,99); $t1_objHandle = $win->{pbT1}->{-handle}; $win->AddButton( -name => 'btnRun2', -size => [50,20], -pos => [4,32], -text => 'Run 2', ); $win->AddProgressBar( -name => 'pbT2', -size => [120,20], -pos => [58,32], -smooth => 1, ); $win->{pbT2}->SetRange(0,99); $t2_objHandle = $win->{pbT2}->{-handle}; my $sb = $win->AddStatusBar(); my $icon = new Win32::GUI::Icon('d:/source/perl/auditutil/images/data_server.ICO'); my $ni = $win->AddNotifyIcon( -name => "NI", -icon => $icon, -tip => "Hello" ); $win->Center(); $win->Show(); Win32::GUI::Dialog(); #### Boss sub winMain_Maximize{ 0 }; sub winMain_Minimize{ 0 }; sub winMain_Resize{ 0 }; sub winMain_Terminate{ $ts1_run = -1; $ts2_run = -1; #join workers. $thread1->join(); $thread2->join(); $win->NI->Remove(); $win->Hide(); return -1; } sub btnRun1_Click{ print "clicked btnRun1 \n"; if($ts1_run){ $win->{btnRun1}->Text('Run 1'); $ts1_run = 0; }else{ $win->{btnRun1}->Text('Stop 1'); $ts1_run = 1; } return 1; } sub btnRun2_Click{ if($ts2_run){ $win->{btnRun2}->Text('Run 2'); $ts2_run = 0; }else{ $win->{btnRun2}->Text('Stop 2'); $ts2_run = 1; } return 1; } sub resizeWin { $sb->Move(0, $win->ScaleHeight - $sb->Height); $sb->Resize($win->ScaleWidth, $sb->Height); } sub T1_Timer { print "Timer went off!\n"; return 0; } #### Child 1 sub Thread1{ my $ctr = 1; while( $ts1_run != -1 ){ # die when semaphore says so. if( $ts1_run == 1 && defined($t1_objHandle) ){ #only create a new value when the semaphore is Up Win32::GUI::ProgressBar::SetPos($t1_objHandle, $ctr); $ctr++; $ctr = 0 if $ctr > 99; } select(undef, undef, undef, 0.01); } } #### Child 2 sub Thread2{ my $ctr = 1; while( $ts2_run != -1 ){ # die when semaphore says so. if( $ts2_run == 1 && defined($t1_objHandle) ){ #only create a new value when the semaphore is Up Win32::GUI::ProgressBar::SetPos($t2_objHandle, $ctr); $ctr++; $ctr = 0 if $ctr > 99; } select(undef, undef, undef, 0.01); } } Thanks in advance, Brian Fredette |
From: Robert M. <rob...@us...> - 2007-08-01 00:16:16
|
On 31/07/07, Brian Fredette <bfr...@gm...> wrote: > I found the threads example posted in this group and began playing around. > I've modified the code to add a splash screen using Win32::GUI:SplashScreen, > a timer taken from Tutorial_Part4_timer.pl, a statusbar, and a notifyicon. > For some reason the timer never gets fired. I've tried removing the > splashscreen and threads but it still won't fire. The tutorial works ... > why doesn't this: If you've already gone to the trouble of removing the SplashScreen code and the threads code and seen that the problem still exists, why not post that short code, rather than making us wade through lots of unnecessary stuff? [snip very long code] I can reduce your problem to this: #!/perl -w use strict; use warnings; use Win32::GUI(); my $win = new Win32::GUI::Window( -name => 'winMain', -size => [700, 500], -onResize => \&resizeWin, ); $win->AddTimer('T1', 1000); $win->Show(); Win32::GUI::Dialog(); sub resizeWin { print "Resize Event seen\n"; } sub T1_Timer { print "Timer went off!\n"; } and it stems from the fact that you are mixing the 'Old Event Model' (OEM) with the 'New Event Model' (NEM). The Old Event Model is the one that calls subs by a name composed of the name of the object and the name of the event (e.g. in your example T1_Timer()) The New Event Model is the one that calls a sub that you specify using a -onXXX option to the constructor (e.g. in your example -onResize => \&resizeWin) For (I think) performance reasons, when you specify a NEM event handler using an -onXXX option in the constructor, then the OEM method of working is switched off - hence in your example the T1_Timer() sub is never called (btw in your example the _Maximize, _Minimize, _Resize and _Terminate handlers are never called either) There are 3 ways to fix this. (1) Only use OEM event handlers: remove the -onResize option, and rename resizeWin() as winMain_Resize() (you'll need to remove the winMain_Resize you already have defined) (2) Use only NEM event handlers: add an -onTimer => \&some_timer_hander line to the main window constructor, and rename the T1_Timer() sub some_timer_handler() (3) Leave it all as it is, and add an -eventmodel => 'both' line to the main window constructor. This is not the preferred solution, as it is very easy to get confused and have 2 handlers for the same event - for example if you did this to your code, you would have 2 handlers for the Resize event (resizeWin() and winMain_Resize()) - as it happens, the NEM handler would get called first, and because it doesn't return 0, the OEM handler would get called afterwards. If the NEM handler returned 0, the OEM handler wouldn't get called ... see how this gets confusing ... Regards, Rob. |
From: Brian F. <bfr...@gm...> - 2007-08-02 18:07:04
|
Hi Rob, Thanks for the explanation. Now that you mentioned it I recall reading somewhere OEM versus NEM. Guess I forgot about that. Thats what I get for using old code without deeper reading. Thanks again. Brian On 7/31/07, Robert May <rob...@us...> wrote: > > On 31/07/07, Brian Fredette <bfr...@gm...> wrote: > > I found the threads example posted in this group and began playing > around. > > I've modified the code to add a splash screen using > Win32::GUI:SplashScreen, > > a timer taken from Tutorial_Part4_timer.pl, a statusbar, and a > notifyicon. > > For some reason the timer never gets fired. I've tried removing the > > splashscreen and threads but it still won't fire. The tutorial works > ... > > why doesn't this: > > If you've already gone to the trouble of removing the SplashScreen > code and the threads code and seen that the problem still exists, why > not post that short code, rather than making us wade through lots of > unnecessary stuff? > > [snip very long code] > > I can reduce your problem to this: > > #!/perl -w > use strict; > use warnings; > > use Win32::GUI(); > > my $win = new Win32::GUI::Window( > -name => 'winMain', > -size => [700, 500], > -onResize => \&resizeWin, > ); > $win->AddTimer('T1', 1000); > > $win->Show(); > Win32::GUI::Dialog(); > > sub resizeWin { > print "Resize Event seen\n"; > } > > sub T1_Timer { > print "Timer went off!\n"; > } > > and it stems from the fact that you are mixing the 'Old Event Model' > (OEM) with the 'New Event Model' (NEM). > > The Old Event Model is the one that calls subs by a name composed of > the name of the object and the name of the event (e.g. in your example > T1_Timer()) > > The New Event Model is the one that calls a sub that you specify using > a -onXXX option to the constructor (e.g. in your example -onResize => > \&resizeWin) > > For (I think) performance reasons, when you specify a NEM event > handler using an -onXXX option in the constructor, then the OEM method > of working is switched off - hence in your example the T1_Timer() sub > is never called (btw in your example the _Maximize, _Minimize, _Resize > and _Terminate handlers are never called either) > > There are 3 ways to fix this. > > (1) Only use OEM event handlers: remove the -onResize option, and > rename resizeWin() as winMain_Resize() (you'll need to remove the > winMain_Resize you already have defined) > > (2) Use only NEM event handlers: add an -onTimer => > \&some_timer_hander line to the main window constructor, and rename > the T1_Timer() sub some_timer_handler() > > (3) Leave it all as it is, and add an -eventmodel => 'both' line to > the main window constructor. This is not the preferred solution, as > it is very easy to get confused and have 2 handlers for the same event > - for example if you did this to your code, you would have 2 handlers > for the Resize event (resizeWin() and winMain_Resize()) - as it > happens, the NEM handler would get called first, and because it > doesn't return 0, the OEM handler would get called afterwards. If > the NEM handler returned 0, the OEM handler wouldn't get called ... > see how this gets confusing ... > > Regards, > Rob. > |
From: Robert M. <ro...@th...> - 2007-08-02 18:49:46
|
On 02/08/07, Brian Fredette <bfr...@gm...> wrote: > Thanks for the explanation. Now that you mentioned it I recall reading > somewhere OEM versus NEM. Guess I forgot about that. Thats what I get for > using old code without deeper reading. No problem. Reading may not have got you very far - there is notably little documentation on the NEM (IIRC none in the official docs). Regards, Rob. |
From: Reini U. <ru...@x-...> - 2007-08-10 06:15:23
|
Robert May schrieb: > On 02/08/07, Brian Fredette <bfr...@gm...> wrote: >> Thanks for the explanation. Now that you mentioned it I recall reading >> somewhere OEM versus NEM. Guess I forgot about that. Thats what I get for >> using old code without deeper reading. > > No problem. Reading may not have got you very far - there is notably > little documentation on the NEM (IIRC none in the official docs). There are some testcases in t/05_Timer_01_OEM.t t/05_Timer_02_NEM.t t/05_Timer_03_Interval.t t/05_Timer_04_Kill.t t/05_Timer_05_DESTROY.t -- Reini |