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

Esteemed monks, I am starting to become a little frustrated with 'snippy little things' with my Perl/Tk application, but it hasn't killed me yet so it must be making me stronger. I created a TopLevel, and it works just fine. But now I am creating a second TopLevel and I get these messages on the DOS screen:
Assuming 'require Tk::TopLevel;' at K:\Perl\incontact\start2.pl line 250
Subroutine Tk_cmd redefined at K:/Perl/site/lib/Tk/TopLevel.pm line 14.
Subroutine CreateOptions redefined at K:/Perl/site/lib/Tk/TopLevel.pm line 17.
Subroutine Populate redefined at K:/Perl/site/lib/Tk/TopLevel.pm line 22.
Subroutine Icon redefined at K:/Perl/site/lib/Tk/TopLevel.pm line 29.
Subroutine menu redefined at K:/Perl/site/lib/Tk/TopLevel.pm line 64.
Subroutine Tk::Widget::Toplevel redefined at K:/Perl/site/lib/Tk/Widget.pm line 247.
Tk::Error: Failed to AUTOLOAD 'Tk::Widget::TopLevel' at K:\Perl\incontact\start2.pl line 250
 \&main::doManageUser
 (menu invoke)
Terminating on signal SIGINT(2)
Line 250 is the line
$tlu = $mainwindow->TopLevel ();

In the third block of code below.

Now, the previous TopLevel didn't cause any of these errors that I recall.

Here is the globals - you see I have defined things like handles at the start of the programme:

use Tk; use Tk::DialogBox; use Tk::NoteBook; use Tk::LabEntry; use Tk::BrowseEntry; use Tk::TopLevel; # use Date::Manip; use Text::ParseWords; use Data::Dumper; use strict; # Always! $^W++; # Turn on warnings require "common.pl"; my $config = { DSN => 'DBI:mysql:incontact', MySQLunm => 'root', MySQLpwd => '', PWmaxtries => "3" }; my $state = { cur_user => '', ImpFile => '', ImpCnt => '', ImpDs => ''}; my $DEBUG = 1; my $mainwindow; my $tli; my $tlu; my $dbh; my (@map_fields, @file_fields, @user_fields, @dsources); my $user;
Then here is where the first TopLevel is created:
if (! Exists($tli)) { $tli = $mainwindow->Toplevel(); $tli->title("File Import"); $tli->LabEntry(-label => "File name", -labelPack => [-side => "left", anchor => "w"], -width => 40, -textvariable => \$state->{ImpFile})->grid(); my $tli_ds = $tli->BrowseEntry(-label => "DataSource", -variab +le => \$state->{ImpDs} )->grid(); $tli_ds->focus; my $SQL = "SELECT id, sourcename, sourcedesc from datasour +ce;"; my $sth = $dbh->prepare( $SQL ); $sth->execute; while (($id, $datasource, $ds_desc) = $sth->fetchrow_array +) { $tli_ds->insert('end', ($datasource." ".$ds_desc)); $rec->{$datasource} = ${ds_desc}; $dsources[$id] = $rec; } for ( $li = 0; $li < $imp_field_count; $li++ ) { $tli->Label(-relief => 'sunken', width => 25, text => $fil +e_fields[$li])->grid( my $brb = $tli->BrowseEntry( -label => "", -variab +le => \$map_fields[$li])); $brb->insert('end', @$ref); } $tli->Button(-text => 'Import', -command => \&doImport2)->grid +(-pady => 5, -columnspan => 2); } else { $tli->deiconify(); $tli->raise(); } debug("-doFileImport"); }
Now, that TopLevel creation subroutine is not even called when I try to use this one...
sub doManageUser { my $uname; my @listnames; if ( ! Exists($tlu)) { $tlu = $mainwindow->TopLevel(); $tlu->title("User Management"); my $lb = $tlu->BrowseEntry(-label => 'Username', -variable => +\$uname,)->pack; $lb->bind("<Return>", \&do_search); $lb->focus; my $SQL = "SELECT username FROM user;"; my $sth = $dbh->prepare( $SQL ); $sth->execute; while (my $username = $sth->fetchrow_array) { push @listnames, $username; } $sth->finish; $lb->insert('end', @listnames); $tlu->LabEntry(-label => "First Name", -labelPack => [-side => "left", -anchor => "w"], -width => 20, -textvariable => \$user->{firstname})->pack(-side => "top" +, -anchor => "ne"); $tlu->LabEntry(-label => "Last Name", -labelPack => [-side => "left", -anchor => "w"], -width => 20, -textvariable => \$user->{lastname})->pack(-side => "top", -anchor => "ne"); $tlu->LabEntry(-label => "Password", -labelPack => [-side => "left", -anchor => "w"], -width => 20, -textvariable => \$user->{password})->pack(-side => "top", -anchor => "ne"); $tlu->Button(-text => "Update", -command => \&doUserUpdate)->pack(-side => "bottom"); } else { $tlu->deiconify(); $tlu->raise(); } }
I expect I have missed something basic and obvious, but it is so basic and obvious I cant for the life of me figure out what I have done!

John

Replies are listed 'Best First'.
Re: Unexpected errors using multiple TopLevel's in Perl/Tk
by Mr. Muskrat (Canon) on Jul 28, 2003 at 21:20 UTC
    I thought that I would point out a few things.
    1. Either add -w to the shebang line or use warnings;. $^W++; isn't gonna do what you think in this case.
    2. Module names are case sensitive. Try use Tk::Toplevel; and $tlu = $mainwindow->Toplevel();. (Note the lowercase l's in Toplevel)

    Added: Try this example:

    #!/usr/bin/perl $^W++; my $text = "blah"; print "$test\n";
    It doesn't produce any warnings. Why? Because warnings are generated at compile time not run time. Remove the $^W++; and add -w to the shebang line and run it again. It works now, see? Name "main::test" used only once: possible typo at w.pl line 3.

      See, I told you it would be something simple.

      Thanks Mr Muskrat!

      I have been staring at the various parts of the code for this application since 7:30am and I think I needed a break. As soon as I saw your comment I realised what I had done.

      Thanks also for the warning about $^W++ - I am not sure where I picked that one up, but I will go have a look at the documentation. I have changed this script to use -w on the shebang line.

      ...john