Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

Tk Button state tied to variable

by glenn (Scribe)
on Oct 22, 2014 at 20:45 UTC ( [id://1104706] : perlquestion . print w/replies, xml ) Need Help??

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

How to get TK widget option to accept variable reference? I need to use this in more than one place and it's not an option to store the button in the hashref as this hashref will be updated by other clients.

use Tk; $mw = MainWindow->new(); my $system = {}; $system->{blink}->[0] = "disabled"; #works but does not update as value in hashref changes my $but = $mw->Button(-text=>"Blink Unit", -state=>$system->{blink}->[ +0])->pack(); #does not work as state will not accept variable reference #my $but = $mw->Button(-text=>"Blink Unit", -state=>\$system->{blink}- +>[0])->pack(); =pod *$but->{'Configure'}->{'-state'} = \$system->{blink}->[0]; #overwrite +the location of the value?? =cut

Replies are listed 'Best First'.
Re: Tk Button state tied to variable
by choroba (Cardinal) on Oct 22, 2014 at 22:40 UTC
    Instead of using a tied variable, you can define a subroutine to update the button based on the parameters:
    #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = 'Tk::MainWindow'->new; my $states = [qw[ disabled normal ]]; my @buttons; for my $i (0, 1) { $buttons[$i] = $mw->Button( -text => "Start $states->[$i]", -state => $states->[$i], -command => sub { warn "B$i" }, )->pack; $mw->Entry( -textvariable => \$states->[$i] )->pack; } $mw->Button( -text => 'Apply', -command => sub { blink($_, $states->[$_]) for 0, 1; } )->pack; sub blink { my ($idx, $state) = @_; $buttons[$idx]->configure( -state => $state ); } MainLoop();

    Is it what you wanted?

    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Tk Button state tied to variable ( Tk::Trace )
by Anonymous Monk on Oct 22, 2014 at 22:19 UTC
    Um, yeah, a -textvariable option only works for -text option ... if you want it to work for something else, you have to use Tk::Trace

      Thank you for telling me about trace. It wont accomplish this task as it still requires the widget to accept a variable reference which is updated by task; however, I can use this to implement a text box that updates based on a variable.

Re: Tk Button state tied to variable
by GotToBTru (Prior) on Oct 22, 2014 at 21:41 UTC

    What error messages do you get or what behavior do you observe (and what did you expect)? What is $mw? Is the syntax of your button definition correct?

    1 Peter 4:10
      Updated to include correct syntax that does not accomplish the task.
Re: Tk Button state tied to variable
by glenn (Scribe) on Oct 23, 2014 at 03:39 UTC

    Thanks for telling me about trace. I will give that a try and update with results and working example.

    Works, here is what I did for the next person who needs to know.

    use Tk; use Tk::Trace; use Tk::Text; my $system = {}; @{$system->{gui}->[0]->{cut_ctl_1}} = ("start", "normal"); @{$system->{gui}->[0]->{cut_ctl_2}} = ("remove", "normal"); $system->{gui}->[0]->{progress}->[0] = "Not running"; my $mainwindow = MainWindow->new(); my $but_ctl_1 = $mainwindow->Button(-textvariable=>\$system->{gui}->[0 +]->{but_ctl_1}->[0], -state=>$system->{gui}->[0]->{but_ctl_1}->[1])-> +grid(-row=>0, -column=>0, -sticky=>"nsew"); my $but_ctl_2 = $mainwindow->Button(%{-textvariable=>\$system->{gui}-> +[0]->{but_ctl_2}->[0], -state=>$system->{gui}->[0]->{but_ctl_2}->[1]) +->grid(-row=>1, -column=>0, -sticky=>"nsew"); my $progress = $mainwindow->Scrolled('Text', -scrollbars=>'osoe', -hei +ght=>5, -width=>30)->grid(-row=>2, -column=>0, -sticky=>"nsew"); $progress->Subwidget('scrolled')->insert( 'end', "$system->{gui}->[0]- +>{progress}->[0]" ); #traces: $frame->traceVariable( \$system->{gui}->[0]->{progress}->[0], 'w', [ \ +&text_update, $progress->Subwidget('scrolled')] ); $frame->traceVariable( \$system->{gui}->[0]->{but_ctl_1}->[1], 'w', [ +\&state_update, $but_ctl_1] ); $frame->traceVariable( \$system->{gui}->[0]->{but_ctl_2}->[1], 'w', [ +\&state_update, $but_ctl_2] ); $mainwindow->after(5000, sub{ $system->{gui}->[0]->{progress}->[0] = "RUNNING"; $system->{gui}->[0]->{but_ctl_1}->[1] = "disabled"; }); MainLoop(); sub text_update { my ($index, $value, $op, $t) = @_; return unless $value; $t->delete("1.0", "end"); $t->insert( 'end', "$value" ); return $value; } sub state_update { my ($index, $value, $op, $b) = @_; return unless $value; $b->configure(-state=>$value); return $value; }