Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Dynamically altering Tk buttons

by Llew_Llaw_Gyffes (Scribe)
on Jan 04, 2010 at 06:30 UTC ( [id://815522]=perlquestion: print w/replies, xml ) Need Help??

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

Brethren,

Related to my earlier ruminations concerning a Perl/Tk music player (see Tk UI behavioral oddities (solved problem)), I find myself needing to dynamically change the Play/Pause button in response to user actions. Basically, the button image should switch from a Play icon to a Pause icon when play is started, and switch back to a Play icon when playback is stopped.  (When paused, the icon should not change, but the button's action should toggle between pause and unpause; but that is, of course, a simple matter to handle within the callback function.)

I cannot, however, find any documented way to do this, short of destroying and recreating the button.  Is there in fact any such means?

Replies are listed 'Best First'.
Re: Dynamically altering Tk buttons
by zentara (Archbishop) on Jan 04, 2010 at 14:10 UTC
    ...here is an example for you to check out

    ... the problem is how do you detect the end of playback... is some signal emitted?

    .... i leave the state logic broken, for you to figure out :-)

    #!/usr/bin/perl use strict; use warnings; use Tk; my $mw = Tk::MainWindow->new; my $button = $mw->Button->pack(-side =>'left'); my $button1 = $mw->Button(-text => 'Go ', -state => 'normal')->pack( -side =>'left'); my $x = $mw->Pixmap( -data => qq(/* XPM */ static char * x_xpm[] = { "24 24 2 1", " c None", ". c #000000", " ", " ", " ", " ", " ", " ", " ... ... ", " .. .. ", " ... .. ", " .. ... ", " .... ", " ... ", " ... ", " .... ", " .. .. ", " ... .. ", " .. ... ", " .. .. ", " ... ... ", " ", " ", " ", " ", " "}; )); my $o = $mw->Pixmap( -data => qq(/* XPM */ static char * o_xpm[] = { "24 24 2 1", " c None", ". c #000000", " ", " ", " ", " ", " ", " ", " ...... ", " ........ ", " ... ... ", " .. .. ", " .. .. ", " .. .. ", " .. .. ", " .. .. ", " .. .. ", " .. .. ", " ... ... ", " ........ ", " ...... ", " ", " ", " ", " ", " "}; )); my @toggle = ($x, $o); my @toggle1 = ('Go ','Whoa'); $button->configure( -image => $x, -command => sub { @toggle = @toggle[1, 0]; @toggle1 = @toggle1[1, 0]; $button->configure(-image => $toggle[0]); if ( $toggle1[0] eq 'Go '){ $button1->configure( -text => $toggle1[0], -state => 'normal', ); }else{ $button1->configure( -text => $toggle1[1], -state => 'disabled', ); } } ); Tk->MainLoop;

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku

      Yup, I found that method myself, after some digging.

      How I'm detecting the end of playback is a little sneaky.  I'm spawning the CLI MP3 player application like this:

      $cmd = sprintf($opts{playercmd}, ($listbox->getRow($i))[0]); $player_pid = open($PLAYER, "|$cmd");

      This gets me a blocking open on the player, so that I don't ever get two tracks playing at once, and a child PID back.  But, the child player doesn't terminate on exit.  So then I poll /proc/pid/status every 50ms in my non-Tk event loop, and wait for the status to change to 'zombie', at which point I know playback has finished.  Then I can close the player handle, do any necessary processing, and advance to the next track.  The 50ms response time is too short for the listener to notice, but slow enough in system terms that the task load from the polling is down in the noise.

        and wait for the status to change to 'zombie'

        ha ha ha.... that has got to be the funkiest hack i've ever seen....... didn't they teach you at wizard school to never, NEVER allow zombies even into existence?.... still laughing

        To give you a clue: once you have the filehandle to the process, you can watch for the filehandle( or its filenum' ) to be closed , and then do a kill -9 on the $parent_pid ..... see Perl/Tk front-end to mplayer for other ideas


        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku
Re: Dynamically altering Tk buttons
by Anonymous Monk on Jan 04, 2010 at 07:18 UTC

      This doesn't really answer the question.  This illustrates a checkbutton which has different bitmaps for its selected and unselected states.  A checkbutton, however, has persistent state.  What I need to do is have a regular pushbutton which changes its button bitmap, in a persistent fashion, both in response to UI actions and to remote commands not involving the UI, and which may have more than two visual states.

      I've subsequently discovered that there is, indeed, a simple way to do this; but the documentation of the method is somewhat obscurely buried in Tk::options.  That method is as simple as this:

      $button->configure(-bitmap => 'MyNewBitmap');

      Using this method, I now have multimode buttons that change their button image and foreground color as appropriate depending on what the application is doing, exactly as I wanted.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://815522]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (3)
As of 2024-04-26 01:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found