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

I have tried searching on this and find things close but nothing quite on the money for my problem.

As you see in the code below, I am using -textvariable and the variable is a element in a hash. I have set up four buttons. What I find is that

1: If I assign a whole new hash to the old hash, there is no change picked up and the display does not change. Why not? Is it throwing my old hash away and giving me the address to a new hash?

2: If I assign a scaler literal or a scaler variable to the hash element, it IS picked up and the display changes.

3: If I assign the elements of the hash in a loop from another hash it works.

#!/usr/bin/env perl use warnings; use strict; use Tk; our %FinalNoRecord = ( COMPANY_CODE => 'AB', COMPANY_NAME => 'ABC, Inc.', ); our %FinalNoRecord_change = ( COMPANY_CODE => 'XY', COMPANY_NAME => 'XYZ, Inc.', ); our $company_change = 'Foo, LLC.'; our $mw = MainWindow->new(); $mw->title("hashTkEntryTestcase"); my $topInfoFrm = $mw->LabFrame( -relief => 'groove', -borderwidth => 3, -label => "Final Assembly Information:", -labelside => 'acrosstop' )->pack(-side => 'top', -fill => 'both'); my $companyInfoFrm = $topInfoFrm->LabFrame( -label => "Company Code:", -labelside => 'left' )->pack(-side => 'top', -fill => 'x', -anchor => 'w'); my $companyCodeEntry = $companyInfoFrm->Entry( -width => 3, -textvariable => \$FinalNoRecord{COMPANY_CODE}, )->pack(-side => 'left'); my $companyNameEntry = $companyInfoFrm->LabEntry( -label => "Company Name:", -labelPack => [qw/-side left -anchor w/], -width => 30, -textvariable => \$FinalNoRecord{COMPANY_NAME}, -state => 'readonly', -relief => 'flat' )->pack(-side => 'left', -expand => 1, -anchor => 'w'); my $ChangeHashButton = $mw->Button( -text => "ChangeHash", # This doesn't work. -command => sub{%FinalNoRecord = %FinalNoRecord_change; } )->pack(-side=>'left'); my $ChangeCodeButton = $mw->Button( -text => "ChangeCode", # This does work. -command => sub{ $FinalNoRecord{COMPANY_CODE} = 'LM'; } )->pack(-side=>'left'); my $ChangeNameButton = $mw->Button( -text => "ChangeName", # This also works -command => sub{ $FinalNoRecord{COMPANY_NAME} = $company_change; } )->pack(-side=>'left'); my $ChangeHashLoopButton = $mw->Button( -text => "ChangeHashLoop", # This works too. -command => sub{ for my $key (keys %FinalNoRecord) { $FinalNoRecord{$key} = $FinalNoRecord_change{$key}; } } )->pack(-side=>'left'); my $ExitButton = $mw->Button( -text => "Exit", -command => [$mw=>'dest +roy'] )->pack(-side=>'right'); MainLoop();

Replies are listed 'Best First'.
Re: -textvariable won't update when using hash element
by GrandFather (Saint) on May 09, 2013 at 01:10 UTC

    The problem is that the -textvariable parameter is taking a reference to the value in the hash - you know that of course, but there is a trap. When you assign the new hash to the old hash you are replacing the contents of the old hash, both keys and values, and most likely the values end up stored in a different place so the original reference isn't doing you any good any more. As an illustration of what's going on consider:

    #!/usr/bin/env perl use warnings; use strict; my %fnr = ( COMPANY_CODE => 'AB', COMPANY_NAME => 'ABC, Inc.', ); my %fnr_loop = ( COMPANY_CODE => 'XY', COMPANY_NAME => 'XYZ, Inc.', ); my %fnr_but = ( COMPANY_CODE => 'PQ', COMPANY_NAME => 'PQR, Inc.', ); my $nameRef = \$fnr{COMPANY_CODE}; show('Original'); changeHashLoop(); show('Loop'); changeHashButton(); show('Button'); sub changeHashButton { %fnr = %fnr_but; } sub changeHashLoop { for my $key (keys %fnr) { $fnr{$key} = $fnr_loop{$key}; } } sub show { my ($label) = @_; my $ccRef = \$fnr{COMPANY_CODE}; printf "%8s: %s (%s) FNR: %s (%s)\n", $label, $$nameRef, $nameRef, $$ccRef, $ccRef; }

    Prints:

    Original: AB (SCALAR(0x94a554)) FNR: AB (SCALAR(0x94a554)) Loop: XY (SCALAR(0x94a554)) FNR: XY (SCALAR(0x94a554)) Button: XY (SCALAR(0x94a554)) FNR: PQ (SCALAR(0x94a584))

    Note the change in the address of the FNR value when the hash copy has been made.

    True laziness is hard work

      Thanks! That makes perfect sense. So what is happening is the reference address stored in:

      -textvariable => \$fnr{COMPANY_CODE},

      still exists but has been abandoned after

           %fnr = %fnr_new;

      No change is detected because what was stored at that address didn't change and will never change (unless the abandoned address got recycled.) Correct?

      There are only 10 types of people in this world... those who understand binary, and those who don't.
        "So what is happening is ..."

        Yep, got it in one. I'm sure I've been bitten by this in the dim distant past, and spent considerable time trying to figure out where the bug in Tk was!

        True laziness is hard work
Re: -textvariable won't update when using hash element
by LivingDust (Novice) on May 09, 2013 at 00:13 UTC

    Sorry for the multiple updates, I did find a typo in my code write after posting it, and I fixed it which answered 1/2 of my original question. I am still left with the first question of why doesn't

    %FinalNoRecord = %FinalNoRecord_change;

    get picked up as a change?