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

Gracious monks,
I have sought long and faltered. No where can I find a simple example of how to change a button's appearance when it is pressed while its associated callback runs. It's no good to see the appearance change after the callback finishes, I want a doohickey as simple as changing the button's color while its callback runs. And of course I'll switch the appearance back once the callback/sub is done.

My problem stems from some Win32::OLE calls I'm making that do lots of processing/formatting with Word. They take long enough such that a user might not notice that:

"No matter which value is specified for the -relief option, when the button is pressed with the mouse, its relief will change to 'sunken'." (from Learning Perl/Tk by Nancy Walsh, p. 69)
I want something more dramatic than a sunken button. It doesn't have to be the AIX "running man", a simple change of colors will do--I just can't see the option to do it.

Thanks,
Brig

  • Comment on Tk button appearance while its callback runs

Replies are listed 'Best First'.
Re: Tk button appearance while its callback runs
by rbc (Curate) on Oct 11, 2002 at 03:11 UTC
    Try something like ...
    $myButton->configure( background => 'red' );
    ... basically $widget->configure( ?arg, .. arg?) lets you change the changable options on the widget.
      This is a good idea, but the color change/configure method doesn't seem to fire on behalf of the callback until the whole callback/subroutine finishes. Which is after I've twiddled my thumbs for a while staring at a stupid sunken button while I wait for my Word stuff to finish. Sure, at that point I get the effect, but I want the effect to be concurrent with the processing of the callback, not after.

      Brig

Re: Tk button appearance while its callback runs
by Mr. Muskrat (Canon) on Oct 11, 2002 at 13:51 UTC

    How about changing the cursor to show that it's working?

    $mw->Busy( '-recurse' => 1 ); # your long process goes here $mw->Unbusy( '-recurse' => 1);
      Wonderful!

      At least I get a mouse cursor of an hourglass via
      -cursor => 'watch'
      building on your suggestion. Interestingly, I lose the
      -relief => 'sunken'
      effect unless I include this specifically within the "Busy" call. Trying to sneak in other options such as 'text', 'background', and 'foreground' seems to have no effect, thus these options are commented out in my snippet.

      Thanks,
      Brig

      my $Customized_Command_b; $Customized_Command_b = $tl->Button( -textvariable => \$Custom_Command_label, # previously defined -underline => 0, -borderwidth => $bd_width, -command => sub { $Customized_Command_b->Busy( '-recurse' => 1, -cursor => 'watch', #-text => 'Processing...', -relief => 'sunken', #-background => 'blue', #-foreground => 'blue', ); system $custom_command, @arguments, $formdir, $dir and warn "'Custom Command' problem: ", $? >> 8, "\n" and $ccmd_rc = 1 ; if ($ccmd_rc) { $View_Custom_Log_cb->configure( -background => "red1", -activebackground => "red1", ); } $Customized_Command_b->Unbusy( '-recurse' => 1 ); $tl->raise(); }, )->grid( -column => 5, -row => 14, -columnspan => 6, -sticky => 'nsew', );
Re: Tk button appearance while its callback runs
by BlueBlazerRegular (Friar) on Oct 11, 2002 at 14:54 UTC
    You need to 'update' the screen before the callback runs, like this:

    # # Sets the cursor to the 'busy' cursor # $mw->Busy(-recurse => 1); $mw->update(); # # Callback code goes here # $mw->Unbusy; $mw->update();

    You aren't limited to just setting the 'busy' cursor - you can change widget colors, disable the button, etc. But you need to refresh the screen or else you won't see your changes.

    Pat

      Hi Pat,
      Hmm, this is not panning out. Within the callback, running the Busy method against the widget that invoked the callback achieves the cursor change as noted above, but I'm still not able to change colors, text, etc. even with the 'update' calls.

      However, you have alerted me to the fact that I was not controlling the cursor appearance either. Silly me, I thought that 'watch' was just cross-referenced incorrectly to an hourglass and didn't test using a different cursor style. Now I see that
      -cursor => 'watch'
      was doing nothing for me.

      Thanks,
      Brig

        Well, yet another of my misconceptions (regarding the needfulness of $mw->update) has been brought out into the light of day (where, hopefully, it will wither away and die).

        After some experimentation, I think I have something that does what you want. I had to combine several different things together, but that appears to the 'Tk' way. So without further ado...

        #!/opt/local/bin/perl -w use strict; use warnings; use Tk; my $button_label = 'Push me'; my $mw = MainWindow->new; $mw->geometry("300x200+20+20"); $mw->title( "Tk Testing" ); my $button; $button = $mw->Button( -textvariable => \$button_label, -underline => 0, -foreground => 'blue', -command => sub { my $saved_label = $button_label; $button_label = 'Ouch!'; $button->configure( -relief => 'flat', -activeforeground => 'red', -activebackground => 'green', ); $button->Busy(-recurse => 1 ); sleep( 10 ); $button_label = $saved_label; $button->configure( -relief => 'raised', -foreground => 'blue', ); $button->Unbusy; }, )->pack(-side => 'top', -anchor => 'center', -fill => 'none', -expand => 0, -padx => 5, -pady => 5, ); MainLoop; exit 0; __END__

        Hope this is useful. Even if it isn't, I've learned something, so it wasn't a complete waste. :)

        Pat