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

($row is 1 and $i is 0 in the beginning)
foreach my $key (@keys) { $cells{$row.$i}=$mwwidgets{"sc_list"}->Label(-textvariable=>\ +$info{$key.$row},-relief=>"ridge",-width=>15)->grid(-row=>$row,-colum +n=>$i)->bind('<Double-Button-1>',sub{profile_window($currentrow)}); print $cells{$row.$i}; #$cells{10}->configure(-text=>"bla"); last if ($i==7); $i++; } $row++;

this is just a snippet from a bigger program, but i need some help with why it doesnt work. its supposed to fill the %cells with labels and grid them in the scrolled widget $mwwidgets{"sc_list"} (it's a hash of all widgets). @keys contains the keys for the %info hash, but i dont think it matters here.

the line that right now is a comment is supposed to test if it worked, but the warning tells me it cant call the method on an uninitialized value, same for the print line. the labels are being created though, they also contain the right text and the bind works. what to do?

(btw this is my first post here, no idea if i did the formatting right)

Replies are listed 'Best First'.
Re: Tk: Creating label in hash
by roboticus (Chancellor) on Sep 18, 2013 at 11:21 UTC

    banzai:

    I'd suggest using another dimension in your hash, e.g. $cells{$row}{$i} or adding a delimiter $cells{"$row.$i"}, otherwise your code will have difficulty when your array gets larger. "Hmmm ... $cells{'111'} ... is that row 1 column 11 or row 11 column 1?"

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

Re: Tk: Creating label in hash
by Anonymous Monk on Sep 18, 2013 at 11:06 UTC

    the line that right now is a comment is supposed to test if it worked, but the warning tells me it cant call the method on an uninitialized value, same for the print line. the labels are being created though, they also contain the right text and the bind works. what to do?

    I'm back (network down)

    Well, the cause of uninitialized value is the last link in the chain ->Label(...)->grid(...)->bind(...)

    Label() returns an object, grid() returns that same object, bind returns nothing (actually bind returns an empty string)

    an empty string is not an object so what you store in $cells{$row.$i} is the empty string

    I used Basic debugging checklist item 4 ( Dumper ) to discover this :)

    But like I said earlier,I strongly recommend rethinking the way you write code (Re^5: Multiple frames), for example

    #!/usr/bin/perl -- ## perltidy -olq -csc -csci=10 -cscl="sub : BEGIN END if " -otr -opr +-ce -nibc -i=4 -pt=0 "-nsak=*" use strict; use warnings; use Tk; use Data::Dump qw/ dd /; Main( @ARGV ); exit( 0 ); sub Main { GoTk(); } sub GoTk { my $mw = tkinit( -title => "tk closures people" ); ## the "globals" my %info; my %cells; my $currentrow = 1; ## the oddballs my $row = 1; my $column = 1; for my $key ( qw/ a b c Q 6 42 / ) { my $tvref = \$info{ $key . $row }; $$tvref = "($row)($column) $key"; my $label = $mw->Label( -textvariable => $tvref, -relief => "ridge", -width => 15, )->grid( -row => $row, -column => $column ); $cells{ $key . $row } = $label; ## logic flaw $row++; $column = int rand( 4 ); } ## one callback for entire grid, not one for each label $mw->bind( 'Tk::Label' => '<Double-Button-1>', [ \&Pickett, \$currentrow, \%info ], ## NO CLOSURE!!! ); use Tk::WidgetDump; $mw->WidgetDump; $mw->MainLoop; dd( \%cells, \%info ); } ## end sub GoTk sub Pickett { my( $label, $currentrowref, $info ) = @_; my $e = $Tk::event; my $xy = sprintf( '(%s,%s)', $e->X, $e->Y, ); ## $info->{a1} print "\n$xy $label $currentrowref $$currentrowref\n"; if( $label->isa( 'Tk::Label' ) ) { print "$label ", $label->cget( -text ), "\n"; } } ## end sub Pickett __END__ (210,135) Tk::Label=HASH(0x107489c) SCALAR(0xb9b374) 1 Tk::Label=HASH(0x107489c) (5)(1) 6 (239,145) Tk::Label=HASH(0x10749cc) SCALAR(0xb9b374) 1 Tk::Label=HASH(0x10749cc) (6)(2) 42 ( { 426 => bless({ _TkValue_ => ".label5" }, "Tk::Label"), 65 => bless({ _TkValue_ => ".label4" }, "Tk::Label"), a1 => bless({ _TkValue_ => ".label" }, "Tk::Label"), b2 => bless({ _TkValue_ => ".label1" }, "Tk::Label"), c3 => bless({ _TkValue_ => ".label2" }, "Tk::Label"), Q4 => bless({ _TkValue_ => ".label3" }, "Tk::Label"), }, { 426 => "(6)(2) 42", 65 => "(5)(1) 6", a1 => "(1)(1) a", b2 => "(2)(0) b", c3 => "(3)(0) c", Q4 => "(4)(3) Q", }, )
      I love you. I really do.
Re: Tk: Creating label in hash
by Anonymous Monk on Sep 18, 2013 at 07:47 UTC