ASPN ActiveState Programmer Network  
ActiveState, a division of Sophos
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups
Submit Recipe
My Recipes

All Recipes
All Cookbooks


View by Category

Title: With busy cursor
Submitter: Joe English (other recipes)
Last Updated: 2001/09/08
Version no: 1.0
Category: User Interfaces

 

5 stars 1 vote(s)


Approved

Description:

Tk utility - change the mouse pointer to a watch cursor, execute a script, then restore the original cursor. Works properly even if the script raises an error, [break]s, [return]s, or any other exceptional return code.

Source: Text Source

# Usage: withBusyCursor { script ... }
#
proc withBusyCursor {body} {
    global errorInfo errorCode
    set busy {}
    set list {.}
    # Traverse the widget hierarchy to locate widgets with 
    # a nondefault -cursor setting.
    #
    while {$list != ""} {
        set next {}
        foreach w $list {
            catch {set cursor [$w cget -cursor]}
            if {[winfo toplevel $w] == $w || $cursor != ""} {
                lappend busy $w $cursor
                set cursor {}
            }
            set next [concat $next [winfo children $w]]
        }
        set list $next
    }

    # Change the cursor:
    #
    foreach {w _} $busy {
        catch {$w configure -cursor watch}
    }
    update idletasks

    # Execute the script body.
    #
    set rc [catch {uplevel 1 $body} result]
    set ei $errorInfo
    set ec $errorCode

    # Restore the original cursor settings.
    #
    foreach {w cursor} $busy {
        catch {$w configure -cursor $cursor}
    }

    # Return script result to caller.
    #
    return -code $rc -errorinfo $ei -errorcode $ec $result
}

The license for this recipe is available here.

Discussion:

Got a section of code in a GUI that takes a few seconds to execute?
Wrap it in a call to [withBusyCursor] to give the user feedback.

Known problems: Only tested on Unix; it doesn't seem to always work
on Windows. I'm not sure if it should use [update] or [update idletasks].

Notes: Unlike the BLT [busy] command, this doesn't block user input.
In practice this doesn't seem to be a problem -- when the cursor changes,
users tend to stop clicking until it changes back.

The code also illustrates a useful idiom for breadth-first traversal,
the correct way to pass exceptional return conditions up the call stack,
and one of Tcl's neatest features -- the ability to define new control structures.



Add comment

Number of comments: 1

Block key events..., carl goode, 2006/10/18

This is a very handy piece of code that I use in a number of my applications.  If you add at the top:

grab set -global $window

Where $window is a label/frame or other window with no children who can use key events.  Then before the return statement:

grab release $window

I've discovered this emulates the BLT busy call.  You might need to catch the grab set command if it's invoked before the $window is visible.

Add comment



Highest rated recipes:

1. A minimal debugger

2. Socket based communicatio...

3. With busy cursor

4. Multi-character split

5. LCD Number Display

6. Supporting mouse wheel ...

7. Get widget info

8. Check creditcard numbers ...

9. WSCP - showServerStatus

10. Inline GIF image into ...




Privacy Policy | Email Opt-out | Feedback | Syndication
© 2006 ActiveState Software Inc. All rights reserved.