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

Fellow monks,

I have a TK program and need to share my MainWindow across packages. Please enlighten me on how I can do this.

# my main program

use strict; use warnings; use Tk; our $MW = MainWindow->new(%{$BPP::BPPDEFAULTS::MYDEFAULTS{MAINWINDOW}} +); $MW->geometry('800x700+0+0'); ...
Now I have another file that I want to be able to use $MW in to be the parent of my dialog box.
use Tk::Dialogbox; package BPP::ABOUT; sub AboutBPP { my $about_dialog = $MW->DialogBox( -title=>'About BPP', -background=>'#ffffcc', -buttons=>["Ok"],); my $pic = $about_dialog->Photo(-file=>'money.gif'); $about_dialog->add('Label', -image=>$pic,-background=>'#ffffcc' ) +->grid(-row=>0, -column=>0,-sticky=>'w'); $about_dialog->Show; }#end AboutBPP 1

Update
Here is the error message i'm getting:

Tk::Error: Can't call method "DialogBox" on an undefined value at BPP/ +ABOUT.pm l ine 14. (menu invoke)
THANKS!

Replies are listed 'Best First'.
Re: Sharing Across Packages
by Velaki (Chaplain) on Sep 29, 2006 at 11:55 UTC

    The main package scoped variable $MW is not available inside the package BPP::About.

    Where do you call AboutBPP? You could always call it as

    AboutBPP($MW);
    if it's from the main program.

    And then all you would have to do is add to AboutBPP

    my $MW = shift;

    Hope this helped,
    -v

    "Perl. There is no substitute."
      The main package scoped variable $MW is not available inside the package BPP::About.
      "Package scoped variables" are package variables, they're always accessible using the fully qualified name (like $main::MW). When dealing with our, the only thing you're "scoping" is the possibility to use the non-fully-qualified symbol ($MW) instead of the fully qualified one ($main::MW).

      Flavio
      perl -ple'$_=reverse' <<<ti.xittelop@oivalf

      Don't fool yourself.
Re: Sharing Across Packages
by polettix (Vicar) on Sep 29, 2006 at 12:38 UTC
    Use $main::MW instead of plain $MW inside AboutBPP:
    sub AboutBPP { my $about_dialog = $main::MW->DialogBox(
    But note that following the suggestions given above by others, about passing $MW as the first parameter (an turning the our into a my in main), is probably better and future-proof: use of package variables is more or less equivalent to using global variables.

    Flavio
    perl -ple'$_=reverse' <<<ti.xittelop@oivalf

    Don't fool yourself.
      I tend to think of global variables as "omnipresent variables". Variables contain data, and should be scoped to the smallest enclosing block where the data is being used. Sometimes, it just makes sense to have data available everywhere. Whether the program is running in debugging mode for instance. Or access to the toplevel window of a program. Sometimes it saves a lot of typing (and some schools say the smaller the program, the less bugs it contains) to have an omnipresent variable than pass the variable around to almost every subroutine you call.

      But if you prefer simple rules and don't want to spend a few braincells wondering whether it makes sense to deviate from a guideline, you can always do:

      package main; my $MW = ...; # Create your main window here. sub UNIVERSAL::MW {$MW}
      After all, subroutine are (global) variables as well - but noone ever yells at you for using them.
        some schools say the smaller the program, the less bugs it contains
        ... like this? ;)
        But if you prefer simple rules...
        I'm not sure I always prefer simple rules. In case I have to stick to global variables, I'd prefer that this is clearly marked in some way, which is why I'd avoid this implementation of the "singleton". Moreover, this could be no singleton at all, due to the possible presence of other MW methods in other packages.

        Flavio
        perl -ple'$_=reverse' <<<ti.xittelop@oivalf

        Don't fool yourself.
      In the ABOUT package, how to I include the main package.
      I am getting the following error when I try this $main::MW.
      Can't locate main.pm in @INC (@INC contains: . C:/Perl/lib C:/Perl/sit +e/lib) atline 8.
      I used Data Dumper and the variable is UNDEF.

      use main?????
      use bpp.pl (the main file name)????

      thanks
        You don't need to include anything, packages are always there for you! By default, you *are* in package main unless you specify otherwise. An example will be hopefully useful:
        poletti@PolettiX:~/sviluppo/perl$ nl mikasue.pl 1 #!/usr/bin/perl 2 use strict; 3 use warnings; 4 { # scope reduction 5 our $MW = "Hello, mikasue!"; 6 print "\$MW is '$MW'\n"; 7 print "Current package is ", __PACKAGE__, "\n"; 8 print "\$main::MW is '$main::MW'\n"; 9 } # end of "our" scope 10 package Whatever; 11 no strict; # note: no strict here! 12 print "\$MW is '$MW'\n"; 13 print "Current package is ", __PACKAGE__, "\n"; 14 print "\$main::MW is '$main::MW'\n"; poletti@PolettiX:~/sviluppo/perl$ perl mikasue.pl Name "Whatever::MW" used only once: possible typo at mikasue.pl line 1 +2. $MW is 'Hello, mikasue!' Current package is main $main::MW is 'Hello, mikasue!' Use of uninitialized value in concatenation (.) or string at mikasue.p +l line 12.$MW is '' Current package is Whatever $main::MW is 'Hello, mikasue!'
        Note that you have two warnings regarding line 12. The first one is given during the compilation phase, and refers to the misterious "Whatever::MW" variable. This stems from the fact that, when not using strict, every variable you use actually is the corresponding package variable (in the current package). In line 9 we're entering package "Whatever", so there you are. The second warning happens at run time, when you try to print the content of this variable, that is undefined.

        As you can see (line 7), by default we're in package main.

        Flavio
        perl -ple'$_=reverse' <<<ti.xittelop@oivalf

        Don't fool yourself.
Re: Sharing Across Packages
by Anonymous Monk on Sep 29, 2006 at 11:53 UTC
    Don't do that, instead use
    sub AboutBPP { my $MW = shift; ....