Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Tk MainWindow and another TopLevel spawn order

by Discipulus (Canon)
on Sep 20, 2016 at 09:23 UTC ( [id://1172209]=perlquestion: print w/replies, xml ) Need Help??

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

Hello wise cloister community,

I'm writing a Tk Perl program where i need to spawn immediately a secondary TopLevel window. I generaly use the code similar to that posted below.

All is fine BUT due to the call to the subroutine that draw the secondary windows placed before the MainLoop the secondary window is spawned before the main one and they are ordered incorrectly in the application bar of my OS.

I know the example where a button create a new TopLevel widget, but I want the secondary windows to spawn automatically at start time.

I know that the code is doing what I said it to do; how to code to do what i want?

#!/usr/bin/perl use warnings; use strict; use Tk; use Tk::Pane; my $mw = new MainWindow (); $mw->title(" $0 MAIN"); my $phwin = $mw->Toplevel(); my $fr0 = $mw->Frame(-borderwidth => 2, -relief => 'groove' )->pack(); $fr0->Label(-text => "MAIN $0 MAIN" )->pack(); &secondary_win; MainLoop; ###################################################################### +########## sub secondary_win { # window does not exists if (! Exists($phwin)) { $phwin = $mw->Toplevel(); $phwin->title("SECONDARY"); } # window Exists else { $phwin->deiconify( ) if $phwin->state() eq 'iconic'; $phwin->raise( ) if $phwin->state() eq 'withdrawn'; } my $scrolledframe = $phwin->Scrolled('Frame',-scrollbars => 'osoe' +)->pack(); my $sec_label = $scrolledframe->Label(-text=>'SECONDARY')->pack; }

Thanks in advance

L*

There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

Replies are listed 'Best First'.
Re: Tk MainWindow and another TopLevel spawn order
by pryrt (Abbot) on Sep 20, 2016 at 13:30 UTC

    I played around a little bit: by changing forcing secondary_win to generate the phwin (your !Exists block) and by making $mw process one event, I was able to make the main window draw first and end up first in my Win7 application bar...

    #!/usr/bin/perl use warnings; use strict; use Tk; use Tk::Pane; my $mw = new MainWindow (); $mw->title(" $0 MAIN"); my $phwin; # deleted '= $mw->Toplevel();': force it to be created by s +econdary_win() function my $fr0 = $mw->Frame(-borderwidth => 2, -relief => 'groove' )->pack(); $fr0->Label(-text => "MAIN $0 MAIN" )->pack(); $mw->DoOneEvent(); # appears to force mw to draw itself _before_ seco +ndary_win() creates phwin sleep(1); # makes it obvious that there's a delay; don't use + in production &secondary_win; MainLoop; ###################################################################### +########## sub secondary_win { # window does not exists if (! Exists($phwin)) { $phwin = $mw->Toplevel(); $phwin->title("SECONDARY"); } # window Exists else { $phwin->deiconify( ) if $phwin->state() eq 'iconic'; $phwin->raise( ) if $phwin->state() eq 'withdrawn'; } my $scrolledframe = $phwin->Scrolled('Frame',-scrollbars => 'osoe' +)->pack(); my $sec_label = $scrolledframe->Label(-text=>'SECONDARY')->pack; }
      Many thanks pryrt for your investigation!

      DoOneEvent behaves exactly in the way I want and I suspect that was the function Corion suspected to exists. It seems is not so good documented but I found some hints in the a ptkFAQ and a DoOneEvent POD on github.

      I read on Mastering PerlTk:

      It's actually rather difficult to find a use for DoOneEvent. [..] The DoOneEvent statement was an experiment in which we tried various e +vent masks, in an attempt to determine the optimal combination. You s +ee what we arrived at, which, interestingly, is exactly equivalent to +: $mw->update;

      This is true indeed! using $mw->update; has the same effect of your DoOneEvent call.

      Also ++pryrt to spot the mother of all my errors: $phwin = $mw->Toplevel(); must go after the $mw->update; or $mw->DoOneEvent() or just after the statement or in a sub called after (well is the same..).

      I have no precise notions about the Tk loop works and i tend to use idioms that seem to work, of my own or borrowed.

      Obviously master zentara was on our path before us dissecting how much DoOneEvent can be useful; see Re^2: Term::ReadLine and Tk

      Thanks again!

      L*

      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: Tk MainWindow and another TopLevel spawn order
by Corion (Patriarch) on Sep 20, 2016 at 09:29 UTC

    One ugly (ugly!) way that comes immediately to my mind is to use Tk::after:

    # Spawn as soon as possible when the Tk main loop runs: $phwin->after(0, \&secondary_win);

    I'm sure there also is a Tk event that is fired once the main window has drawn itself, and maybe you can initialize your secondary window from there? I don't readily see convenient callbacks for Window events in the Tk documentation, but there should be more things than just timer events.

Re: Tk MainWindow and another TopLevel spawn order (taskbar order LIFO win32)
by Anonymous Monk on Sep 20, 2016 at 17:31 UTC

    Weird way to write code :) you need to pass arguments to subroutines :)

    This is how it works on win32

    #!/usr/bin/perl -- use strict; use warnings; use Tk; my $two = tkinit(qw/ -title 2 /); ## second in taskbar my $mw = tkinit(qw/ -title 1 /); ## first in taskbar $mw->focusForce; MainLoop; __END__

    Taskbar order on win32 with tk is LIFO

    alt+tab order is unrelated to taskbar order

      Weird way to write code :)

      yes I'm here to learn a better way! ;=)

      Many thanks and ++put_your_name_here for the hint about LIFO order, good to know but i'm curious to know where you found this information or if just comes from your tries.

      Anyway I prefere the pryrt's solution because your using tkinit is in reality creating two distinct indipendent MainWindows: they appear in LIFO order but if you close one of them the other continue to exist.

      How can i retrieve more infos about tkinit anyway? in the Tk source I just see:

      @EXPORT = qw(Exists Ev exit MainLoop DoOneEvent tkinit); [..] sub tkinit { return MainWindow->new(@_) }

      It is just a shortcut to call for a MainWindow creation?

      L*

      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

        but i'm curious to know where you found this information or if just comes from your tries.

        Just from tries, its simpler than reading the source

        How can i retrieve more infos about tkinit anyway? in the Tk source I just see: It is just a shortcut to call for a MainWindow creation?

        Its one of those things monkey see, and yes its just a shortcut , its defined inside Tk.pm, just like MainLoop

        sub tkinit { return MainWindow->new(@_) } sub MainLoop { unless ($inMainLoop) { local $inMainLoop = 1; while (Tk::MainWindow->Count) { DoOneEvent(0); } } }

        Anyway I prefere the pryrt's solution ...

        Yes, parents kill children, but you don't gotta let the user kill the window so you have to recreate it, just hide/show

        #!/usr/bin/perl -- use strict; use warnings; use Tk; my $mw = MakeMain(); my $phwin = MakePhwin( $mw ); $mw->focus; $mw->WidgetDump; MainLoop; sub MakePhwin { my( $mw ) = @_; my $phwin = $mw->Toplevel; $phwin->protocol( 'WM_DELETE_WINDOW', [sub{shift->withdraw}, $phwi +n], ); $phwin->Label(-text => "Close me hit the little x" )->pack; return $phwin; } sub MakeMain { my $mw = tkinit(@_); $mw->Button( -text => "Restore phwin", -command => sub { $_->deiconify for grep $_->isa('Tk::Toplevel'), $Tk::widget->toplevel->children; }, )->pack; $mw->update; return $mw; }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1172209]
Approved by Athanasius
Front-paged by kcott
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2024-03-29 07:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found