Tk Usage FAQ (Frequently Asked Questions)

Tk Usage FAQ (text) (http://tcl.sourceforge.net/faqs/tk/tkfaq.txt)

Tk Usage FAQ (Frequently Asked Questions)

This FAQ will address commonly asked questions about usage of the Tk Toolkit. By providing answers to commonly asked questions in this document, it is hoped that new users of Tk may suffer less frustration getting started with Tk, and that readers of news:comp.lang.tcl may suffer less frustration reading/answering these questions repeatedly.

This FAQ can be obtained from the Tcl FTP archive (209.17.179.230) (ftp://ftp.tcl.tk/pub/tcl/) in the /pub/tcl/FAQ directory. This FAQ has been primarily subsumed by the more dynamic Tcl'ers Wiki (http://wiki.tcl.tk/).

For additional information on Tcl as well as pointers to other documentation and code, see the FAQ maintained by Larry Virden (lvirden at cas org):

FAQ: Tcl Introductory FAQ (http://www.purl.org/NET/Tcl-FAQ/)
which resides on the Tcl FTP archive (ftp://ftp.tcl.tk/pub/tcl/) as /pub/tcl/FAQ/tcl-faq.part0*.

For information on usage of the Tcl programming language, see the posting by Joe Moss (joe at morton rain com):

FAQ: Tcl Language Usage FAQ (http://www.psg.com/~joem/tcl/faq.html)
which resides on the Tcl FTP archive (ftp://ftp.tcl.tk/pub/tcl/) as /pub/tcl/FAQ/tcl-faq-usage.

For additional information about using Tcl/Tk, see the Tcl'ers Wiki (http://wiki.tcl.tk/).

Comments, suggestions, and contributions to this FAQ are welcomed by Jeffrey Hobbs (jeff at hobbs org).

Legend:


Last generated: Tue Jul 12 03:07:52 PM PDT 2005 by Jeffrey Hobbs (jeff at hobbs org) Tk Usage FAQ (Frequently Asked Questions)

Tk Usage FAQ (Frequently Asked Questions)

Tk Usage FAQ (text) (http://tcl.sourceforge.net/faqs/tk/tkfaq.txt)

Tk Usage FAQ (Frequently Asked Questions)

This FAQ will address commonly asked questions about usage of the Tk Toolkit. By providing answers to commonly asked questions in this document, it is hoped that new users of Tk may suffer less frustration getting started with Tk, and that readers of news:comp.lang.tcl may suffer less frustration reading/answering these questions repeatedly.

This FAQ can be obtained from the Tcl FTP archive (209.17.179.230) (ftp://ftp.tcl.tk/pub/tcl/) in the /pub/tcl/FAQ directory. This FAQ has been primarily subsumed by the more dynamic Tcl'ers Wiki (http://wiki.tcl.tk/).

For additional information on Tcl as well as pointers to other documentation and code, see the FAQ maintained by Larry Virden (lvirden at cas org):

FAQ: Tcl Introductory FAQ (http://www.purl.org/NET/Tcl-FAQ/)
which resides on the Tcl FTP archive (ftp://ftp.tcl.tk/pub/tcl/) as /pub/tcl/FAQ/tcl-faq.part0*.

For information on usage of the Tcl programming language, see the posting by Joe Moss (joe at morton rain com):

FAQ: Tcl Language Usage FAQ (http://www.psg.com/~joem/tcl/faq.html)
which resides on the Tcl FTP archive (ftp://ftp.tcl.tk/pub/tcl/) as /pub/tcl/FAQ/tcl-faq-usage.

For additional information about using Tcl/Tk, see the Tcl'ers Wiki (http://wiki.tcl.tk/).

Comments, suggestions, and contributions to this FAQ are welcomed by Jeffrey Hobbs (jeff at hobbs org).

Legend:


Questions

Click on the question to see its answer.

  1. Building and Installing Tk et al on my system

    1. Are there binaries available for my system?
    2. How do I get Tcl/Tk to compile/work on my machine?
    3. Why does the link step says that some of the functions Tcl needs are missing when I am trying to build it?
    4. How do I add BLT to a Tcl(X)/Tk?
    5. How do I create a dynamically loadable library for Tcl/Tk?
    6. How do I use Tk as a DLL with Tcl?
    7. Where are the .lib files for building shared libraries on Windows?
  2. Running Tk applications

    1. Where can I get info on porting my Tk3 application to Tk4? to Tk8?
    2. How do I get my wish application to execute on Unix (I just get a wish prompt!)?
    3. How do I run Tcl/Tk scripts by double-clicking on Windows/Mac?
    4. How can I get Tk to use send (I get security error messages)?
      Does send work on Windows/Mac?
    5. How can I ignore send from other applications?
    6. Does Tcl/Tk read a resource/startup file?
    7. How can I call Tk scripts from a C program?
    8. Why does Tk look funny in CDE/VUE?
  3. Tk application bindings (mouse and keyboard)

    1. How can I change the default class bindings?
    2. How can I delete a binding?
    3. How can I bind to the arrow keys?
    4. How can I get window manager's mouse bindings to work in my Tk application?
    5. How can I add new actions to an existing binding?
    6. How do the mouse buttons map when I have less than 3 buttons?
  4. Tk user interface questions

    1. How can I set X11 resources for a wish application in an app-defaults file?
    2. Can I choose a particular user interface look and feel?
      How do I get native look and feel on Windows/Mac?
    3. How can I change the Tk cursor?
    4. How can I change the default colors in Tk?
    5. How do I specify fonts in Tk?
  5. Tk window manager interaction questions

    1. How can I get the geometry of my window (I get 1x1+0+0)?
    2. How can I raise or lower a window?
    3. How can I withdraw/iconify a window?
      How can I remap a withdrawn window?
    4. How can I use Tk in a subwindow of a non-Tk application?
    5. How can I mix interactions between Xt and Tk/Tcl?
    6. How can I bind the ResizeRequest event?
    7. What is the difference between wm and winfo?
    8. How can I prevent my toplevel from being destroyed?
      How do I make my toplevel ignore the window manager delete button?
    9. How can I prevent my toplevel from being iconified?
    10. How can I keep my toplevel on top?
    11. Is Tk fully ICCCM compliant?
  6. Tk canvas widgets questions

    1. How can I get output from a Tk canvas?
    2. How can I fill a canvas area which is bounded by lines as opposed to a shape like a polygon, oval, etc.?
    3. How can I raise/lower canvas window objects or draw graphics onto a window object inside a canvas?
    4. How can I detect when the canvas has been resized?
    5. How can I use a list of coordinates in a variable to create a polygon (or any other item)?
    6. How can I speed up canvas performance?
    7. How can I put/print an image on the canvas?
    8. Why doesn't the canvas seem to start at 0,0?
    9. Does the canvas have a see method?
    10. How can I draw lines on the canvas?
  7. Tk entry widgets questions

    1. How can I initialize an entry widget with some text?
    2. How can I limit entry widget input (length or type of chars)?
  8. Tk listbox widgets questions

    1. How can I select multiple items that are not adjacent in the listbox at one time?
    2. How can I select items in more than one Tk listbox at a time?
    3. How can I avoid fractional white space at the end of a resizable listbox?
    4. How can I scroll multiple listboxes with one scrollbar?
    5. Why doesn't .listbox curselection or selection get return the proper item when I make a button binding to my listbox?
    6. Can I have different colored lines in a listbox?
  9. Tk menu widget questions

    1. How can I get the tearoff menu to reflect changes in the regular menu?
    2. Why do I have problems accessing item/index 0 of my menu?
    3. How do know when I am over a specific entry in a menu?
  10. Tk text widgets questions

    1. How can I pack a text widget so that it can be resized interactively?
    2. Why do I get an extra newline from the text widget?
    3. How can I check to see if the text widget contents have changed?
    4. How can I maintain read-only sections of a text widget?
    5. Is there an overwrite/overstrike mode for text/entry widget?
    6. How can I always see the end of the text widget?
    7. Does the text widget have undo?
    8. What are the visible lines in a text widget?
  11. Miscellaneous Tk widget questions

    1. How can I create a scrollable window of buttons?
    2. How can I create a widget with an upper case name?
    3. How can I vertically align radio/check buttons regardless of font?
    4. How can I group a set of radiobuttons together?
  12. Tk image questions

    1. Does Tk support JPEG/GIF/XPM/etc?
    2. How can I specify bitmap/image patterns on the command line instead of as a file name?
      What is the format of the -data option for images?
    3. How do I get Tk to recognize the transparency in my GIF images?
    4. How can I get bitmaps created with image to work with -stipple?
  13. Tk geometry manager questions

    1. How can I find my invisible windows when using the packer?
    2. How can I get cget to return the correct size of a resized widget?
      (.widget cget -width|height returns the wrong size!)
    3. How can I clear the geometry settings for a toplevel?
    4. How can I add a row/col to the grid?
  14. Miscellaneous Tk questions

    1. How can I get the name of my own interpreter?
    2. How can I destroy every window except '.'?
    3. How can I get drag & drop functionality in my program?
    4. How can I get a double-click to ignore a single-click?
    5. How can I warp the mouse pointer?
    6. How do I run wish programs without a display?
      How do I run my wish program on a server?
    7. Is there a difference between stand-alone Tk and the Tk plugin?
    8. How can I do terminal emulation in Tk?
  15. Questions on Tk related extensions/applications

    1. What is incrTcl/incrTk?
    2. What is BLT?
    3. What is Tix?
    4. Is there a GUI builder available?
      What is XF/Visual Tcl?
    5. Is there a spreadsheet/table widget in Tk?
      What is TkTable?
    6. What other languages besides Tcl does Tk work with?
      What is this (Perl|Scheme|Guile|.*)/Tk I've heard about?
  16. Reporting bugs, Asking further questions, Other resources

    1. My question isn't answered here. What do I do now?
      What is the netiquette for posting to the newsgroup?
    2. I think I found a bug in Tk. How do I go about reporting it?
    3. There's a bug in the FAQ. How do I go about reporting it?
    4. What documentation can I find online?

Questions and Answers

1. Building and Installing Tk et al on my system

1.1. Are there binaries available for my system?

Tcl/Tk binaries are freely available for Mac, Windows and many unix varieties at:

ActiveTcl binaries (http://www.activestate.com/Tcl)

The sources are freely available from:

Tcl FTP archive (ftp://ftp.tcl.tk/pub/tcl/)
See Tcl Developer Xchange (http://www.tcl.tk/) for more information.


1.2. How do I get Tcl/Tk to compile/work on my machine?

Look in the Tcl distribution for the file called porting.notes. This will contain a collection of notes that various people have provided about porting Tcl to various machines and operating systems. There is also a file called README which should be read FIRST - before doing anything else with the code (this should always be one's first step with any package). Further, there is a changes file which details what has changed since the last release - be sure to read this to see what might need to change in your programs.


1.3. Why does the link step says that some of the functions Tcl needs are missing when I am trying to build it?

Did you run the configure program first (via sh ./configure or equivalent)? Without doing this, things such as strtoul or strerror are sometimes mentioned as missing.

Tcl includes equivalents for at least the following functions and include files which may not be found on some systems:

dirent.h       limits.h	      stdlib.h	     string.h	    opendir.c
strerror.c     strstr.c	      strtol.c	     strtoul.c	    strtod.c


1.4. How do I add BLT to a Tcl(X)/Tk?

From (ghowlett at fast.net) (George A. Howlett) we get the answer:

Instead of adding TclX to blt_wish, try it the other way. Add BLT to wishx. It's pretty simple.

In the file ./<platform>/tkXAppInit.c, add the a call to the BLT initialization routine right after line 116.

    if (TkX_Init(interp) == TCL_ERROR) {
        return TCL_ERROR;
    }
    if (Blt_Init(interp) != TCL_OK)) {
        return TCL_ERROR;
    }

Link wishx with libBLT.a and that's it.

Note: It is better to use the new dynamic loading capabilities of Tcl7.5+. BLT2.1+ and TclX7.5.2+ have the ability to be dynamically loaded modules. See their docs on building them as shared libraries and then see the Tcl man page load for loading it into the system at runtime.


1.5. How do I create a dynamically loadable library for Tcl/Tk?

There are examples for building a dynamically loadable library for any supported Tk platform. You can find this at ftp://ftp.tcl.tk/pub/tcl/misc/example.{zip,tar.gz,tar.Z}.


1.6. How do I use Tk as a DLL with Tcl?

As of 8.4, the core has been changed to fully support the dynamic loading of Tk into Tcl, including the starting of the event loop. A simple

package require Tk
should suffice.


1.7. Where are the .lib files for building shared libraries on Windows?

They are distributed with the ActiveTcl binaries:

ActiveTcl binaries (http://www.activestate.com/Tcl)


2. Running Tk applications

2.1. Where can I get info on porting my Tk3 application to Tk4? to Tk8?

Get the Tk3 to Tk4 porting notes from http://tcl.ActiveState.com/doc/tk4.0.ps. This is also covered in an appendix in the 2nd edition of Welch's Tcl/Tk book. From Tk4 to Tk8, there were fewer incompatibilities but more major features introduced. See http://tcl.activestate.com/software/tcltk/8.0.html for a list of the new features and some notes on upgrading.


2.2. How do I get my wish application to execute on Unix (I just get a wish prompt!)?

For Unix, most systems require a full pathname to the interpreter. So you cannot start a wish script out as

#!wish -f

Likewise, many Unix systems have a maximum length of characters that you can put on a #! line. If you exceed this, you do not get the behavior you expect. So do not try to put something like:

#!/projects/somethingverylong/bin/wish -f

followed by your wish code. Keep the lines short - under 32 characters is recommended. Another option is the following:

#!/bin/sh
# This line makes the next one a comment in Tcl \
exec /path/to/wish "$0" ${1+"$@"}

the /path/to/ is unnecessary if you know that wish is in the user's path. Be careful to make sure that you are referencing the correct version of wish. Tk4+ installs its libraries and executable with the version number attached by default.


2.3. How do I run Tcl/Tk scripts by double-clicking on Windows/Mac?

For Windows, the installation should associate .tcl to launch wish. However, if this is not done properly, you can do it yourself by going to Explorer->View->Options->File Types and creating a file type to associate to .tcl that has the open action as "C:\Program Files\Tcl\bin\wish83.exe" "%1" %* (or whereever you chose to have wish installed).

You can optionally create an Edit action as well. Don't choose notepad as that doesn't understand Unix text files (which just use a line feed for the end of a line, as opposed to carriage return and line feed on Windows and just carriage return on the Mac. I recommend finding a copy of emacs, but write will do.

As for the Mac, it's a little more complicated. Jim Ingham tells us:

There are two things here. One is using scripts in TEXT resources. The other is double-clickable apps.

1) TEXT resources: Make a named resource of type TEXT in the app or any of its shared libraries, and source it in with the command:

source -rsrc resourceName

2) Double-Clickable Apps: define a proc called tkOpenDocument. To get this to source at startup, you will have to do something like put it in the Tk TEXT resource of the Tk shared library, or some other script that gets sourced before or during the Tk startup. In it you can either do this to make a droplet:

proc tkOpenDocument {args} {
   foreach file $args {
      after idle [list source $file]
   }
}

The after idle is necessary if you load any other extensions or scripts in the startup, since the tkOpenDocument gets run for the Original Open Document event gets run in the Tk_Init procedure...

Or just source in the code for your application, for instance using the source -rsrc from 1 above.


2.4. How can I get Tk to use send (I get security error messages)?
Does send work on Windows/Mac?

Alternate forms of this question often mention that Tk send is broken, or ask how to use xauth.

Since Tk 3.3, the X11 xauth security mechanism is used. While this provides more security, it does require the user to do a bit more setup to use the send command. The man page for send describes how to solve this question for the average user. For those interested in further reading on auth, look at ftp://ftp.neosoft.com/pub/tcl/alcatel/docs/Xauthority.gz.

You can configure Tk to not depend on xauth by modifying Makefile.in to comment out the following:

# To turn off the security checks that disallow incoming sends when
# the X server appears to be insecure, reverse the comments on the
# following lines:
#SECURITY_FLAGS =
SECURITY_FLAGS = -DTK_NO_SECURITY

Note: It's not a good idea to disable security if security is an issue for you. You may want to consult your sysadmin before doing this.

send is not supported on the Mac or Windows platforms. Windows has the dde command that can work similarly to send, but uses the native platform DDE mechanism.


2.5. How can I ignore send from other applications?

Delete the send command. This removes the interpreter's name from the X11 property (won't show up in another wish's winfo interps) and disables incoming send processing. You can delete the send command with:

rename send {}


2.6. Does Tcl/Tk read a resource/startup file?

Yes, although the name and location varies by platform.

		tclsh			wish
Unix		~/.tclshrc		~/.wishrc
Windows		~/tclsh.rc		~/wishrc.tcl
Macintosh	(Someone tell me what it is for the Mac)

~ translates into the user's home directory, which usually means C:\ on Windows.


2.7. How can I call Tk scripts from a C program?

Several simple examples have been posted to comp.lang.tcl. Eric Bleeker (ericbl at paramount.nikhefk.nikhef.nl) was gracious enough to package his up and place it at ftp://ftp.neosoft.com/pub/tcl/alcatel/code/tkHelloWorld*. This program assumes that you have installed the Tcl and Tk libraries, header files, etc.

Alternatively, you can look into creating a dynamically loadable library of your C code for Tcl/Tk. There are some basic examples for all platforms at ftp://ftp.tcl.tk/pub/tcl/misc/example.{zip,tar.gz,tar.Z}.


2.8. Why does Tk look funny in CDE/VUE?

The problem is that this strangely designed window managers set X resources for *foreground, *background, *Font, etc..., which gets imposed on Tk. The real problem is that CDE apps rely on these resources being set (no sane defaults). The following is a quick wrapper solution.

The solution is provided as a shell script which wraps around any Tk program which you might normally run. It is assumed that you have xrdb and the program in your regular path. If this is how you normally launch your app:

	tkcon -slave "lappend auto_path /my/dir" &

then you would now do: (notice that the wrapper backgrounds automatically)

	uncde tkcon -slave "lappend auto_path /my/dir"
#!/bin/sh
#
# uncde
#
# This script will temporarily remove those lame global resource bindings
# that screw with Tk applications.  It launches the Tk app (which is assumed
# to be in your path), gives it a few seconds to load up, and then restores
# the old resources.
#
# Example usage:	uncde tkcon -slave "set a 50"

if test ! "$1"; then
    echo "usage: $0 command options"
    exit
fi

## Cache the old resources
OLD_RESOURCES=`xrdb -query`

## Remove what we didn't want
echo "removing *foreground, *background and *Font resources"
xrdb -remove <<STOP
*foreground:
*Font:
*background:
STOP

exec ${1+"$@"} &
echo "\"$1\" backgrounded as process $!"

## Give time for Tk to load up and avoid the old resources
sleep 3

## Add back the old stuff
echo "resetting all resources to defaults"
xrdb -merge <<STOP
$OLD_RESOURCES
STOP

3. Tk application bindings (mouse and keyboard)

3.1. How can I change the default class bindings?

All default class bindings for Tk widgets are initialized in $tk_library/tk.tcl. Use this file as a guide to implement new bindings.


3.2. How can I delete a binding?

Give an empty-string command to the bind invocation. For example, to disable the Delete key in all entry fields:

bind Entry <Delete> {}

Also, see the documentation for the bind and bindtags commands. There are several ways to disable or modify which types of bindings (instance, class, etc.) occur and the order in which they are processed.

In Tk4.2+, there is an event command which allows for the specification of virtual event names, like <<Cut>>. Tk4.2+ uses these for bindings such as Cut/Copy/Paste. Deleting bindings from a virtual event works like so:

event delete <<Cut>> <Control-x>


3.3. How can I bind to the arrow keys?

Arrow keys are bound to <Left>, <Right>, <Up> and <Down>. Under X11, keys are referred to by their keysym. One can use either xmodmap -pk or the xev program to determine what the keysym a particular key on a keyboard is currently generating.

If the keysym that is being used is not known by Tk, you may have to edit its ks_names.h file. There is a note in this file that indicates that one should not edit it - but this is where the keysym must be for it to be recognized.


3.4. How can I get window manager's mouse bindings to work in my Tk application?

Some window managers, such as mwm, define mouse button bindings which cause Tk some problems. Try renaming your window manager's startup file (something like ~/.twmrc for instance) and copy in a startup file from a login id that works.


3.5. How can I add new actions to an existing binding?

The binding model in Tk4 allows you to have bindings trigger for a widget instance without modifying that of the widget's class. The following example sets a global variable to the item which a user selects in a listbox without interfering with Tk's highlighting of that item:

bind .listbox <ButtonRelease-1> { set my_global [%W get [%W nearest %y]] }

If you want your binding on the widget instance to be the only event to trigger (avoiding any possible class or all binding), then add a break at the end of the binding, like so:

bind .listbox <Double-Button-1> { destroy %W; break }

If you still want to add to an existing binding, you need to have a + on the first line of the bind command, like so:

bind .listbox <Double-Button-1> {+ destroy %W; break }

See the documentation for bind and bindtags for more information.


3.6. How do the mouse buttons map when I have less than 3 buttons?

For Windows and 2 button mice, <Button-1> is the left button and <Button-3> is the right button. You may have an OS extension which emulates the 2nd button by pressing both buttons simultaneously.

For Mac OS X, multi-button mice are fully supported, should you just plug one in. However, since one button is still the standard, you should be aware to allow for Command-click and Option-click as alternatives in your UI.

For those who lack <Button-2>, the only core bindings made for that are fast scanning of listbox, entry and text widgets. Programmers with potential users in this category should be sensitive to this loss and try and offer alternatives (like <Shift-Button-1>).


4. Tk user interface questions

4.1. How can I set X11 resources for a wish application in an app-defaults file?

Read the documentation for the option command. Then you should consider something like the following - assume the program name is xwf.

The following are two general purpose functions to put into a library:

# get_env varName
#   Looks up the environment variable named $varName and returns its value
#   OR {} if it does not exist
proc get_env varName {
    global env
    if {[info exists env($varName)]} { return $env($varName) }
}

# loadAppDefaults classNameList ?priority?
#   Searches for the app-default files corresponding to classNames in
#   the order specified by X Toolkit Intrinsics, and loads them with
#   the priority specified (default: startupFile).
proc loadAppDefaults {classNameList {priority startupFile}} {
  set filepath "[split [envVal XUSERFILESEARCHPATH] :] \
		[envVal XAPPLRESDIR] \
		[split [envVal XFILESEARCHPATH] :] \
		/usr/lib/X11"
  foreach i $classNameList {
    foreach j $filepath {
      if {[file exists $j/$i]} {
	option readfile $j/$i $priority; break
      }
    }
  }
}

Now, here is what you would put into xwf:

option add Tk.BoldFont "*-lucida sans-Bold-R-Normal-*-100-*" widgetDefault
loadAppDefaults {xwf XWF} userDefault

This sets a program default, then load any defaults specified in the user's default resources and finally any site or general app-defaults resource. Of course, you would want to add some xwf command line handling to allow the user to override things at execution time.

Chris Milam contributes the following modification of loadAppDefaults which follows the X11R5 method of merging app-default files from several sources.

# loadAppDefaults classNameList ?priority?
#   Searches for the app-default files corresponding to classNames in
#   the order specified by X Toolkit Intrinsics (R5), and loads them with
#   the priority specified (default: startupFile).
proc loadAppDefaults {classNameList {priority startupFile}} {
  set lang [envVal LANG]
  if {[string length $lang] > 0} { set lang /$lang }
  set filepath "/usr/lib/X11${lang}/app-defaults \
                [split [envVal XFILESEARCHPATH] :] \
                [envVal XAPPLRESDIR]${lang} \
                [split [envVal XUSERFILESEARCHPATH] :]"
  foreach i $classNameList {
    foreach j $filepath {
      if {[file exists $j/$i]} {
        option readfile $j/$i $priority;
      }
    }
  }
}


4.2. Can I choose a particular user interface look and feel?
How do I get native look and feel on Windows/Mac?

Tk4 has a Motif compliant look and feel (LAF). If you want a more conformant Motif LAF, put:

set tk_strictMotif 1

as close to the beginning of your program as possible. Tk reads that variable dynamically to determine whether it should maintain a strict Motif LAF.

Tk4 strives to be Motif compliant and does not currently use either XView or Xt based widgets in its user interface, so an OpenLook compliant (or similar toolkit) interface is not possible.

Tk8 has native LAF for Windows and Mac (with Unix maintaining the Motif LAF). Tk8 uses the LAF of the system it is on without exception. You can get the Tk4 LAF on non-Unix platforms only by modifying the core files to use the Unix widget counterpart code.

The Tk tile extension (http://tktable.sourceforge.net/tile/) (support starting in 8.4) provides truly themed widgets tied to the native widget systems.


4.3. How can I change the Tk cursor?

See cursors for a list of available cursors. On the Mac you can also use crsr and CURS style cursors by the name of the resource, and on Windows (as of 8.3) you can use .ico cursors. On Unix it possible to define your own cursors. The Tk_GetCursor man page describes this in detail, but in short you create an X bitmap file like so:

#define face_width 16
#define face_height 12
#define face_x_hot 7
#define face_y_hot 7
static char face_bits[] = {
  0x00, 0x01, 0x30, 0x06, 0x0c, 0x18, 0x04, 0x10, 0x32, 0x26, 0x32, 0x26,
  0x01, 0x40, 0x81, 0x40, 0x09, 0x48, 0x12, 0x24, 0xe2, 0x23, 0x04, 0x10,
  0x0c, 0x18, 0x30, 0x06, 0xc0, 0x01, 0x00, 0x00};

and then configure your cursor with . configure -cursor [list @path_to_xbm_file fgColor]

Here's a little proc to make an entire application go busy while it's doing something. Just call it with the commands you want to execute, and the watch cursor will be displayed for the time it takes the commands to complete. Note that any new windows will have their normal cursor.

proc busy {cmds} {
    global errorInfo

    set busy {.app .root}
    set list [winfo children .]
    while {[llength $list]} {
	set next {}
	foreach w $list {
	    set class [winfo class $w]
	    set cursor [lindex [$w configure -cursor] 4]
	    if {![string compare $w [winfo toplevel $w]] || \
		    [string compare {} $cursor]} {
		lappend busy [list $w $cursor]
	    }
	    set next [concat $next [winfo children $w]]
	}
	set list $next
    }

    foreach w $busy {
	catch {[lindex $w 0] configure -cursor watch}
    }

    update idletasks

    set error [catch {uplevel eval [list $cmds]} result]
    set ei $errorInfo

    foreach w $busy {
	catch {[lindex $w 0] configure -cursor [lindex $w 1]}
    }

    if {$error} {
	error $result $ei
    } else {
	return -code $error $result
    }
}


4.4. How can I change the default colors in Tk?

You can change the default colors by modifying your X resource database for your personal use or use the Tk convenience command tk_setPalette. You can do the first using whatever method you usually use to add/modify X resources (X default file, etc.), or you can use the Tk option command to change the option database from within a Tk application. Tk also has the command tk_bisque which reverts Tk4 to using the Tk3 default colors. The easiest way to set your application to one general scheme is via tk_setPalette like so:

tk_setPalette pink

For more information, see your system's documentation for loading X resources, and/or the Tk man page for the option and tk_setPalette commands.


4.5. How do I specify fonts in Tk?

For Tk4, fonts are specified in different ways for Unix and Windows/Mac environments. For Unix, you want to specify fonts in the X11 font spec format, like so:

.widget configure -font "-adobe-courier-bold-r-normal--8-80-75-75-m-50-iso8859-1"

Often you will see *s replace certain elements of the above font spec. You can get a full list of fonts on your machine from the command xlsfonts. For Windows/Mac environments, the fonts are specified like so:

## Font spec: {Family Size Style}
.widget configure -font {Courier 12 {}}
.widget configure -font {Helvetica 18 {Bold Italic}}

For valid font spec formats on Win/Mac, Tk will find a font, even if it is not the specified one. You should always be careful which fonts you choose because only a core set can be expected to be on any given machine.

Tk8 has a new font mechanism that allow for the easy specification of fonts (as above) for all platforms, creating your own named fonts, and commands to query and manipulate information about available fonts.


5. Tk window manager interaction questions

5.1. How can I get the geometry of my window (I get 1x1+0+0)?

If you start wish interactively and type:

puts [wm geometry .]

you will get something like:

200x200+90+90

The actual numbers may vary depending on X11 defaults, window managers, etc. If you put the same thing in a script, though:

#!/usr/local/bin/wish
puts [wm geometry .]

You will instead get this:

1x1+0+0

This will happen because you are requesting geometry information before the window has actually been drawn. In general, before you start asking about window sizes, use the update command so that the geometries of the windows can be resolved. Changing the above script to this will give the expected results:

#!/usr/local/bin/wish
update
puts [wm geometry .]


5.2. How can I raise or lower a window?

The commands raise and lower are used to change a window's position in the stacking order, as well as adjust toplevel windows to be raised/lowered with respect to other windows.


5.3. How can I withdraw/iconify a window?
How can I remap a withdrawn window?

wm withdraw <toplevel> will take a window off the screen without iconifying it.

wm iconify <toplevel> will iconify a window (how it looks iconified is up to the window manager).

wm deiconify <toplevel> will remap or deiconify the window.


5.4. How can I use Tk in a subwindow of a non-Tk application?

From (faustus at CS.Berkeley.EDU) (Wayne A. Christopher):

Create the Tk toplevel window but don't map it (wm withdraw .toplevel). Then re-parent the window to be a subwindow of your other one and then map it. I have done this when the Tk application is a separate process, but if it's the same process I think you will get into trouble with the event loop, since each toolkit wants control.

Note: Tk8 provides better access to this functionality, a spin-off from making the Tk plugin work.


5.5. How can I mix interactions between Xt and Tk/Tcl?

Tk has a new event loop which provides easier interaction than previous answers dictated. The following answer is provided by Paolo Brutti (Paolo.Brutti at tlsoft.it):

void XtEventSetup(ClientData xtconn, int flags)
{
  static Tcl_Time maxDelay={0, 300000}; /* To process non-X events */

  Tcl_WatchFile((Tcl_File)xtconn, TCL_READABLE);
  Tcl_SetMaxBlockTime(&maxDelay);
}

int XtDoEvent(Tcl_Event *evPtr, int flags)
{
  while (XtPending())
    XtProcessEvent(XtIMAll);
  return 1;
}

void XtEventCheck(ClientData xtconn, int flags)
{
  Tcl_Event *event;

  if(XtPending()) {
    event	= (Tcl_Event *)ckalloc(sizeof(Tcl_Event));
    event->proc	= XtDoEvent;
    Tcl_QueueEvent(event, TCL_QUEUE_TAIL);
  }
}

void tkGo (void)
{
  extern Widget topLevel;
  Tcl_File xtconn;
  int xtfd = ConnectionNumber(XtDisplay(topLevel));

  xtconn = Tcl_GetFile((ClientData)xtfd, TCL_UNIX_FD);

  Tcl_CreateEventSource(XtEventSetup, XtEventCheck, (ClientData)xtconn);
  while (1) {
    Tcl_DoOneEvent(TCL_ALL_EVENTS);
  }
}


5.6. How can I bind the ResizeRequest event?

The ResizeRequest event is used (typically by window managers) to interpose on configuration changes before they occur, possibly preventing them from occurring altogether and support for it was removed in Tk4. There is almost no imaginable case where Tk scripts should really be asking for ResizeRequest events; people tended to use them when what they really wanted was Configure events (which trigger after the resize has occured), and this produced very strange behavior in their programs.

Try bind .widget <Configure> { puts "%W is now %w x %h" } instead.


5.7. What is the difference between wm and winfo?

wm (short for window manager) is used for managing or finding information about toplevels, while winfo (short for widget info) is for querying info about all types of widgets.

For example, wm geometry . will give you the size of the main toplevel, including window manager decoration, as perceived by the window manager. However, winfo geometry . returns only the size of . as perceived by Tk.


5.8. How can I prevent my toplevel from being destroyed?
How do I make my toplevel ignore the window manager delete button?

You can capture the window manager delete window action with the following:

wm protocol .toplevel WM_DELETE_WINDOW { puts "Don't delete me" }

This overrides the window manager's default action, so if you wanted to have a clean up procedure execute before closing the window, you have to make sure to close the window yourself.

The wm protocol will catch window manager generated close requests, not internally generated destroy .toplevel calls resulting from user commands. Presumably, you have control over all user command processing, and can call private close functions for explicit confimation before removing the window.


5.9. How can I prevent my toplevel from being iconified?

You can trap the unmapping of the window and immediately redisplay it with the following:

bind .toplevel <Unmap> { wm deiconify %W }


5.10. How can I keep my toplevel on top?

There are two methods for keeping your toplevel on top. Make your choice depending on your needs:

The first method is for modal dialogs, where you want to ensure that the dialog does not get obscured by its associated toplevel window. It is assumed that you already have done a local grab on the dialog to make it modal. All you have to do then is call wm transient .dialog .master to ensure that the dialog will remain on top. This is somewhat window manager dependent, but works in general.

The second method is more forceful, for when you want a window to not be obscured at all. To create this effect, do the following:

bind .toplevel <Visibility> {
    if {[string match %W .toplevel] &&
	[string compare %s VisibilityUnobscured]} {
	raise %W
	update
    }
}

Windows doesn't handle <Visibility> like Unix, but it does handle transient well. However, if you really want something forceful, then the following is it. It is a proc which just calls raise on your toplevel and reschedules itself:

proc keep_raised toplevel {
    if {[winfo exists $toplevel]} {
	raise $toplevel
	after 1000 [info level 0]
    }
}

Tim Wilson points out a way on Windows to effectively raise the toplevel above all other windows (including dialogs), with the help of Robin Becker's DLL caller extension at http://www.jessikat.demon.co.uk/docdll.html.


5.11. Is Tk fully ICCCM compliant?

In short, no. However, it is possible to make Tk more ICCCM compliant through the use of a few wm methods. The following are a couple examples which effect window manager interaction:

wm command . "$argv0 $argv"
wm client . [info hostname]

6. Tk canvas widgets questions

6.1. How can I get output from a Tk canvas?

The Tk canvas has a postscript method which allows one to create an Encapsulated Postscript file describing the canvas. This works for images as of 8.3.

To get better postscript support, as well as a generally enhanced canvas, get the Tk dash patch (http://purl.oclc.org/net/nijtmans/dash.html) by Jan Nijtmans (j.nijtmans at chello nl) (part of 8.3+).


6.2. How can I fill a canvas area which is bounded by lines as opposed to a shape like a polygon, oval, etc.?

You must use a polygon if you want to fill an area bounded by some lines.


6.3. How can I raise/lower canvas window objects or draw graphics onto a window object inside a canvas?

Use raise .widget and lower .widget to adjust window objects relative to each other. However, graphics objects cannot be raised above window objects on the canvas. See the canvas man page for the full set of options.


6.4. How can I detect when the canvas has been resized?

You need to bind a command to the Configure event, like this:

bind .canvas <Configure> { puts "%W is now %w %h" }


6.5. How can I use a list of coordinates in a variable to create a polygon (or any other item)?

This is actually a pure Tcl question, but it comes up frequently in this context, so here we go...

All canvas items require two or more coordinates on creation, which define the initial position and/or shape of the item. If you have each coordinate in a separate variable, or you are using a constant value, then creating canvas items is simple. For example:

    .myCanvas create rectangle $x1 $y1 $x2 $y2 -fill blue
    .myCanvas create text 100 250 -text "Hello, world"

Many times, though, the coordinates don't each exist in a separate variable. They may be a list in a single variable that was read from a file, or returned from some calculation routine, or extracted from some other list of coordinates. In this case, you need to break the list of coordinates up before the canvas command is executed. Use the eval commands for this. Here are several examples:

# Example 1
# Given a list of two coordinates, create a text item
#
set coords {150 50}
eval .myCanvas create text $coords -text hello

# Example 2
# Here's a routine that returns coordinates for a rectangle centered
# around a point, and some example uses.
#
proc CenteredRectangle {x y width height} {
    return [list [expr {$x - $width/2.0}] \
	    [expr {$y - $height/2.0}] \
	    [expr {$x + $width/2.0}] \
	    [expr {$y + $height/2.0}]]
}
eval .myCanvas create rectangle [CenteredRectangle 80 5 10 75]
eval .myCanvas create rectangle [CenteredRectangle 5 80 75 10]
eval .myCanvas create oval [CenteredRectangle 140 110 75 50]

# Example 3
# Here's a routine which creates a text label surrounded by
# a rectangle, with both of them centered around a given point.
#
proc CenteredBoxLabel {w x y text} {
    set id [$w create text $x $y -text $text -anchor center]
    eval $w create rectangle [$w bbox $id]
}
CenteredBoxLabel .myCanvas 33 42 "Hello, world"

If you have a list of coordinate pairs, e.g. {{25 10} {30 12} {35 14}},
then an extra step is required to make it a flat list.  Try this:

# Example 4
# Starting with a list of pairs...
#
set coordPairs {{25 10} {30 12} {35 14}}

# ... flatten out the list into just a list of numbers (as in
# the above examples).
#
set flatList [eval concat $coordPairs]

# Now, follow the same strategy as in the examples above.
#
eval .myCanvas create line $flatList

In summary, carefully read the docs for eval, concat, and list so that you can combine the coordinate data with the canvas create command to form a valid Tcl command which can be executed.

Note: As for Tk 8.3, the canvas items will accept the coords in the list form, saving the call to eval.


6.6. How can I speed up canvas performance?

Often times coding style changes can result in increased performance, but the canvas has its limits. The Tk dash patch (http://purl.oclc.org/net/nijtmans/dash.html) by Jan Nijtmans (j.nijtmans at chello nl) has many canvas improvements, including one or two that can improve performance in some situations (part of the core in 8.3+).


6.7. How can I put/print an image on the canvas?

To put an image into the canvas you must first create it with image create ... and then embed that image into the canvas. For example:

image create photo my_image -file [file join $tk_library demos images teapot.ppm]
pack [canvas .c]
.c create image 0 0 -anchor nw -image my_image

Tk supports the printing of images in 8.3+. You can otherwise get this functionality by grabbing the Tk dash patch (http://purl.oclc.org/net/nijtmans/dash.html) by Jan Nijtmans (j.nijtmans at chello nl).


6.8. Why doesn't the canvas seem to start at 0,0?

The canvas coords are skewed by the highlight border and the relief. By default, they overlap onto the canvas coord space. There are two ways to deal with this:

## Method 1, zero out the highlightthickness and borderwidth
## (borderwidth defaults to zero) anyway
.canvas configure -borderwidth 0 -highlightthickness 0

## Method 2, adjust the canvas position to expose 0,0 properly
.canvas xview moveto 0
.canvas yview moveto 0

Method 2 is better, but you must do it anytime you adjust the canvas borderwidth or highlightthickness.


6.9. Does the canvas have a see method?

The canvas lacks a see method like that available in the text or listbox widgets. The following code provides the equivalent functionality for a canvas:

## "see" method alternative for canvas
## Aligns the named item as best it can in the middle of the screen
## Behavior depends on whether -scrollregion is set
##
## c    - a canvas widget
## item - a canvas tagOrId
proc canvas_see {c item} {
    set box [$c bbox $item]
    if {![llength $box]} return
    if {![llength [$c cget -scrollregion]]} {
	## People really should set -scrollregion you know...
	foreach {x y x1 y1} $box {
	    set x [expr {round(2.5*($x1+$x)/[winfo width $c])}]
	    set y [expr {round(2.5*($y1+$y)/[winfo height $c])}]
	}
	$c xview moveto 0
	$c yview moveto 0
	$c xview scroll $x units
	$c yview scroll $y units
    } else {
	## If -scrollregion is set properly, use this
	foreach {x y x1 y1} $box {top btm} [$c yview] \
		{left right} [$c xview] {p q xmax ymax} \
		[$c cget -scrollregion] {
	    set xpos [expr {(($x1+$x)/2.0)/$xmax - ($right-$left)/2.0}]
	    set ypos [expr {(($y1+$y)/2.0)/$ymax - ($btm-$top)/2.0}]
	}
	$c xview moveto $xpos
	$c yview moveto $ypos
    }
}


6.10. How can I draw lines on the canvas?

A few simple bindings turn the canvas into a simple drawing tool:

bind .c <ButtonPress-1> {
    set %W(line) [list %W coords [%W create line %x %y %x %y] %x %y]
}
bind .c <B1-Motion> {
    eval [lappend %W(line) %x %y]
}
bind .c <ButtonRelease-1> {
    eval [lappend %W(line) %x %y]
}

7. Tk entry widgets questions

7.1. How can I initialize an entry widget with some text?

You can use the -textvariable option for an entry widget as follows:

set default "foobar"
entry .foo -width 25 -textvariable default

or you can specifically insert text into the entry (only works when the entry widget is configured as -state normal):

entry .foo
.foo insert 0 "foobar"


7.2. How can I limit entry widget input (length or type of chars)?

You want to make use of combination of the entry widget's -textvariable option and the tcl variable trace function. Here is a limited example:

proc forceInt {name el op} {
    global $name ${name}_int
    if {[string compare {} $el]} {
	set old  ${name}_int\($el)
	set name $name\($el)
    } else { set old ${name}_int }
    if {![regexp {^[-+]?[0-9]*$} [set $name]]} {
	set $name [set $old]
	bell; return
    }
    set $old [set $name]
}

pack [label .la -text {Integer 2: {^[-+]?[0-9]*$}}] -anchor w
pack [entry .a -textvariable myVar] -fill x -expand 1
trace variable myVar w forceInt
set myVar {}

You can see a more complex example as a Tk plugin (http://www.tcl.tk/software/plugin/) at http://www.purl.org/net/hobbs/tcl/tclet/entrylimit.html.

The 8.3+ entry widget has advanced built-in validation facilities to make this task much easier.


8. Tk listbox widgets questions

8.1. How can I select multiple items that are not adjacent in the listbox at one time?

Use the -selectmode option of the listbox to specify what type of selection you desire. The modes multiple and extended will allow you to select multiple non-contiguous entries. See the listbox man page for more information.


8.2. How can I select items in more than one Tk listbox at a time?

The default for Tk's listbox widget is to export its selection as the X selection. There can only be one of these at a time. To turn off this behavior in Tk, use -exportselection false when you create the listbox. Alternatively, place the following command at the beginning of your script:

option add *Listbox.exportselection false


8.3. How can I avoid fractional white space at the end of a resizable listbox?

Use -setgrid 1 when you create the listbox. Note that only one widget can properly have setgrid set per toplevel. See the options man page for more information. It works like so:

listbox .l -setgrid 1 -yscrollcommand [list .s set]
scrollbar .s -command [list .l yview]
pack .s -side right -fill y
pack .l -side top -fill both -expand 1
.l insert end one two three four five six seven eight nine ten LAST

Note: You may have only one widget per toplevel use -setgrid.


8.4. How can I scroll multiple listboxes with one scrollbar?

Scrollbars have a -command option which is used to tell scrollable widgets (e.g. listbox, text, entry) how to position themselves when the scrollbar is moved. This command typically looks like:

scrollbar .scroll -command {.scrollable_widget yview}

where xview can substitute for yview. Before the command is executed, however, it will have two numbers concatenated to it. The numbers are fractional positions which indicate how the scrollable widget should position itself. Thus, to have a single scrollbar control multiple widgets, simply use a procedure as the scroll command, and have that procedure scroll as many widgets as you would like. The procedure should take a two arguments (i.e. the fractional positions). The following example will connect multiple listboxes to one scrollbar and correctly handle button bindings in each for single/browse selection:

set BOXES [list .lb0 .lb1 .lb2 .lb3]

proc LBset args {
    global BOXES
    foreach lb $BOXES { eval $lb $args }
}

proc LBselect {sellist} {
    global BOXES
    foreach lb $BOXES {
	$lb selection clear 0 end
	foreach item $sellist {
	    $lb selection set $item
	}
    }
}

proc LBscroll args {
    eval .sy set $args
    LBset yview moveto [lindex $args 0]
}

scrollbar .sy -orient v -command [list LBset yview]
pack .sy -fill y -side right

foreach lb $BOXES {
    if {[info tclversion] == 8.0} {
	listbox $lb -exportselection no -selectmode browse -yscrollcommand LBscroll
	pack $lb -side left -fill both -expand 1

	bind $lb <ButtonPress-1> {
	    LBset selection clear 0 end
	    LBset selection set [%W nearest %y]
	}
	bind $lb <B1-Motion> {
	    LBset selection clear 0 end
	    LBset selection set [%W nearest %y]
	    LBset see [%W nearest %y]
	}
	bind $lb <ButtonRelease-1> {
	    LBset selection clear 0 end
	    LBset selection set [%W nearest %y]
	}
    } else {
	## As of Tcl 8.1, we have a <<ListboxSelect>> virtual event
	## that we can trigger on - much easier
	## This works just fine with any -selectmode
	listbox $lb -exportselection no -selectmode browse -yscrollcommand LBscroll
	pack $lb -side left -fill both -expand 1

	bind $lb <<ListboxSelect>> {
	    LBselect [%W curselection]
	}
    }
}

for {set i 100} {$i} {incr i -1} {LBset insert end $i}

To get proper behavior with the keys as well, you will have to shadow the bindings for key movement found in $tk_library/listbox.tcl.


8.5. Why doesn't .listbox curselection or selection get return the proper item when I make a button binding to my listbox?

The best way to get the selected item during a button click event on a listbox is to use the following code:

bind .listbox <Button-1> { set item [%W get [%W nearest %y]] }

This ensures that the item under the pointer is what will be returned as item. The reason .listbox curselection can fail is because the items in curselection are not set until the Listbox class binding triggers, which is after the instance bindings by defaults. This is the same reason for which selection get can fail, but it will also fail if you set the -exportselection option to 0.


8.6. Can I have different colored lines in a listbox?

This is possible with the standard listbox as of 8.3. Some attempts have been made to make megawidget listboxes with this functionality based on the text or canvas widget. The Tix (http://tix.sourceforge.net/) megawidget extension provides an extended listbox.


9. Tk menu widget questions

9.1. How can I get the tearoff menu to reflect changes in the regular menu?

At the moment torn-off menus will not reflect changes made to the original menu. This functionality is slated for an upcoming revision of the menu system in Tk. It's possible to do this now by tracking the associated tearoff using the -tearoffcommand option for menus. This allows you to specify a command that will be executed when the menu is torn off. The widget names of the menu and tearoff menu (tearoffs are created as toplevels with the name .toplevel.tearoff<id> when torn off) are appended to this command before it is evaluated.


9.2. Why do I have problems accessing item/index 0 of my menu?

Tearoffs are new to Tk4 and the new default for menus. They now occupy index 0 of the menu when they are present. You can exclude them by passing -tearoff 0 to each menu or by placing the following line at the beginning of your code:

option add *Menu.tearoff 0


9.3. How do know when I am over a specific entry in a menu?

Tk menu entries are not first class widgets, thus they do not generate their own <Entry> and <Leave> events. However, Tk8 provides the virtual event <<MenuSelect>> that simulates this. An example of its use can be found in the $tk_library/demos/menu.tcl file for Tk8. In Tk4, this can be simulated with a binding to <Any-Motion>.


10. Tk text widgets questions

10.1. How can I pack a text widget so that it can be resized interactively?

When using the pack geometry manager, use -expand 1, as in the following:

pack [text .text] -fill both -expand 1

When using the grid geometry manager, do the following:

grid [text .text] -sticky news
grid rowconfigure 0 -weight 1
grid columnconfigure 0 -weight 1


10.2. Why do I get an extra newline from the text widget?

For internal reasons, the text widget maintains a newline at the end of the text widget. In order to avoid having this added to what was actually input into the text widget, use .text get 1.0 end-1c to get the full text out of a text widget.


10.3. How can I check to see if the text widget contents have changed?

The text widget does not have a -textvariable option like the entry widget, so you must be more devious in determining when the contents have changed.

If the contents of the text widget are known to be small, then a simple solution would be to cache the original contents and use string compare $cache [.text get 1.0 end-1c] to check for changes.

A more general solution that some have recommended is to make bindings that set a global flag when the text widget is edited. This is often imperfect because you have to make sure to account for all bindings which might edit the widget. Also, you don't really want these bindings to trigger all the time, but rather just once after any save command. Alternatively, you could place a wrapper proc around the text widget which intercepts any insert/delete calls:

pack [text .text]
set .text 1; # Represents whether text is SAVED or not
rename .text ..text
proc .text args {
    global .text
    if {[regexp {^(ins|del).*} [lindex $args 0]]} { set .text 0 }
    uplevel ..text $args
}

The only thing that misses is direct C calls and embedded window addition. Don't forget to set .text 1 when you save text.


10.4. How can I maintain read-only sections of a text widget?

Tk 8.3 introduced a disabled state option for tags, which enables this feature. If you want the entire text widget to be read-only, set the -state option of the text widget to disabled.

Prior to 8.3, to create read-only sections in a text widget, you should make use of the text widget tag facility. The following is a minimal example of this:

pack [text .text]
.text tag configure readonly -background yellow
rename .text ..text
proc .text args {
    if {[string match ins* $args] &&
	[lsearch -exact [.text tag names [lindex $args 1]] readonly]>-1} return
    if {[string match del* $args]} {
	if {[string compare {} [lindex $args 2]]} {
	    if {[string compare {} [eval .text tag nextrange \
		readonly [lrange $args 1 2]]]} return
	} else {
	    if {[lsearch -exact [.text tag names \
		[lindex $args 1]] readonly]>-1} return
	}
    }
    uplevel ..text $args
}


10.5. Is there an overwrite/overstrike mode for text/entry widget?

Not by default, but you can change the tkTextInsert and tkEntryInsert library procedures to include this with the following:

proc tkTextInsert {w s} {
    global tkPriv
    if {[string match {} $s] || [string match "disabled" [$w cget -state]])} {
        return
    }
    if {[catch {
        if {[$w compare sel.first <= insert]
                && [$w compare sel.last >= insert]} {
            $w delete sel.first sel.last
        }
    }] && [info exists tkPriv(overwrite)] && $tkPriv(overwrite)} {
        if {[$w compare "insert+[string len $s]c" < "insert lineend"]} {
            $w delete insert "insert+[string length $s]c"
        } else {
            $w delete insert "insert lineend"
        }
    }
    $w insert insert $s
    $w see insert
}
 
proc tkEntryInsert {w s} {
    global tkPriv
    if {[string match {} $s]} {
        return
    }
    if {[catch {
        set insert [$w index insert]
        if {([$w index sel.first] <= $insert)
                && ([$w index sel.last] >= $insert)} {
            $w delete sel.first sel.last
        }
    }] && [info exists tkPriv(overwrite)] && $tkPriv(overwrite)} {
        $w delete insert [expr {[$w index insert]+[string length $s]}]
    }
    $w insert insert $s
    tkEntrySeeInsert $w
}

Thus you just set the tkPriv(overwrite) variable to 0/1 to switch between the overwrite and insert modes.

Note that Tk 8.4 moves all the private tk variables and procedures (tk[A-Z]*) into the Tk namespace. tkEntryInsert becomes tk::EntryInsert and so forth.


10.6. How can I always see the end of the text widget?

The problem is you add text to the text widget but you can't see it because it is now off the screen. Instead of requiring any interaction from the user, you can use either of the following lines of code:

.text see end ;# works anytime for text widgets
# OR
.text yview moveto 1 ;# works for other widgets with scrollbars attached


10.7. Does the text widget have undo?

The text widget has built-in undo/redo in 8.4 (TIP#26, see the 8.4 text docs), but you can simulate undo functionality for earlier versions of Tk. The method is similar to maintaining read-only sections of a text widget, whereby the programmer must catch every instance of insert and delete and store them.

Depending on whether you want unlimited undo, you also want redo, or you want to capture tags as well, the exact functionality changes. Examples of working undo functionality have been posted on news:comp.lang.tcl and can be found via http://groups.google.com/advanced_group_search?as_ugroup=comp.lang.tcl.


10.8. What are the visible lines in a text widget?

To find the range of characters visible in the text widget, simply use the index function:

set firstChar [$text index @0,0]
set lastChar [$text index @65535,65535]

11. Miscellaneous Tk widget questions

11.1. How can I create a scrollable window of buttons?

The easy way to do this is to make the buttons the children of a canvas widget, place them in the canvas with canvas create window ... and attach a scrollbar to the canvas. For example:

scrollbar .sy -orient v -command ".c yview"
canvas .c -yscrollcommand ".sy set"
pack .sy -fill y -side right
pack .c -fill both -expand 1 -side left
set x 2
set y 2
for {set i 0} {$i<20} {incr i} {
    button .c.b$i -text [list Button $i] -width 10 -command [list puts "$i pressed"]
    .c create window $x $y -window .c.b$i -anchor nw
    incr y [winfo reqheight .c.b$i]
}
.c configure -scrollregion [list 0 0 [winfo reqwidth .c.b0] $y] \
	-width [winfo reqwidth .c.b0]


11.2. How can I create a widget with an upper case name?

You can't. Tk widget names may not begin with a capital letter as those are reserved for widget class names (this does not apply to any other commands). Specific instances of widgets must begin with a lower case letter. This enables X11 resource definitions to distinguish between a class and an instance.


11.3. How can I vertically align radio/check buttons regardless of font?

Note the following example:

radiobutton .times -text Times -anchor w -value Times
radiobutton .helvetica -text Helvetica -anchor w -value Helvetica
radiobutton .courier -text Courier -anchor w -value Courier
pack .times .helvetica .courier -side top -fill x

Note that you are using anchor west in the widgets themselves, and not in the packer. This lets the packer produce full width buttons.


11.4. How can I group a set of radiobuttons together?

To group radiobuttons, simply give all the buttons in a group the same -variable name. Since the default variable name is selectedButton for all radiobuttons, if no -variable is used, then all belong to the same group.

radiobutton .left.b1 -text "Left 1"  -variable leftChoice -value left1
radiobutton .left.b2 -text "Left 2"  -variable leftChoice -value left2
radiobutton .left.b3 -text "Left 3"  -variable leftChoice -value left3

radiobutton .right.b1 -text "Right 1" -variable rightChoice -value right1
radiobutton .right.b2 -text "Right 2" -variable rightChoice -value right2
radiobutton .right.b3 -text "Right 3" -variable rightChoice -value right3

12. Tk image questions

12.1. Does Tk support JPEG/GIF/XPM/etc?

As of Tk4.2, Tk supports XBM (X bitmap) for bitmaps as well as PPM (portable pixmap, a 24 bit format) and GIF (graphics interchange format) for photo images.

The Tk Image Extension (http://sourceforge.net/projects/tkimg) by Jan Nijtmans (j.nijtmans at chello nl) contains format handlers for XBM, XPM, JPEG, PNG and TIFF and the pixmap image type. Further image formats can be added via DLLs with the Tk C command Tk_CreateImageType (along with code to read that format, of course). Img is part of the ActiveTcl binaries.


12.2. How can I specify bitmap/image patterns on the command line instead of as a file name?
What is the format of the -data option for images?

For XBM and PPM formatted images, the image command in Tk allows you to pass a -data option that would contain the image data in the same format as you'd have in a file.

Note: The Tk plugin (http://www.tcl.tk/software/plugin/) and Tk8.0+ can read base64 encoded GIF data via -data. Tk 8.3+ can read binary GIF data through -data.


12.3. How do I get Tk to recognize the transparency in my GIF images?

Tk uses a hack for transparency in GIF images. If you have a GIF89 image that has the transparency index set, you need to set the global Tcl variable TRANSPARENT_GIF_COLOR to the color which you want the show through (in general, the background of the widget you are placing it on). Use the following code as an example:


    label .x
    set TRANSPARENT_GIF_COLOR [.x cget -bg]
    image create photo x -file image.gif
    .x configure -image x

Tk8 removes the need for this hack, properly implementing transparency in GIF images. Donal Fellows went further in 8.4 to provide access to transparency information in an image at the Tcl level. See the photo man page for more.


12.4. How can I get bitmaps created with image to work with -stipple?

At the moment, you can't. Bitmaps created with image create bitmap ... do not use Tk_DefineBitmap, which is required for -stipple to know it's a bitmap. Instead, you'll have to use the old format for using bitmaps in stipples, like so:

.canvas create rect 10 10 80 80 -fill black -stipple @/path/to/my.bmp

It's not a simple C fix for the above problem, but it's on the core ToDo list.


13. Tk geometry manager questions

13.1. How can I find my invisible windows when using the packer?

The situation: A window is created, say .w1, followed by another window, say .w2. The command pack .w1 -in .w2 is used to pack .w1 inside of .w2. The pack command completes successfully, and pack info .w1 indicates that things are as expected. However, .w1 isn't visible! Where is it?

	button .w1 -text Hello;	# create .w1
	frame .w2;		# create .w2
	pack .w1 -in .w2;	# pack .w1 inside .w2 
	pack .w2;		# pack .w1 in main window
				# where's the button?

The explanation: (based on a posting by (js at aelfric.bu.edu) (Jay Sekora))

The short answer is raise .w1. In the example .w1 is positioned properly inside .w2, and all the sizing glue that lets .w1 and .w2 adjust their sizes based on each other will work, but .w1 is underneath .w2, because windows are stacked in the order they are created in, by default. You can change the stacking order explicitly with the raise command, in this case raise .w1.


13.2. How can I get cget to return the correct size of a resized widget?
(.widget cget -width|height returns the wrong size!)

Don't use a widget's cget method, use winfo width|height .widget instead. The cget method will only tell you what the widget wanted to be or what you told it to be with .widget configure -width|height .... If the packer resizes it to fill the slave space, or the user resizes it, then only winfo will return the actual new size. To summarise:

<widget> cget -width
<widget> cget -height

These give you back the size that you asked for in units specific to the widget, e.g. it could be pixels, lines, characters, miles etc. This size is used by the widget to calculate the initial size in pixels of the whole widget (including borders etc.). The meaning of these options is totally widget specific.

winfo reqwidth <widget>
winfo reqheight <widget>

This gives you the size in pixels that the widget has calculated is optimal given all of the options set on that widget. This information is passed to the geometry manager which decides what the actual size of the widget should be.

winfo width <widget>
winfo height <widget>

These give you the actual size of the widget as set by the geometry manager. This may be larger or smaller then the requested size.


13.3. How can I clear the geometry settings for a toplevel?

If you want to have Tk resize your toplevel to what the toplevel requires (ie: the user might have resized it, or a widget was removed), use [wm geometry $toplevel].


13.4. How can I add a row/col to the grid?

There is a simple Tcl solution for this, provided by Stephen Uhler, (with modification by Donal Fellows):

# insert rows or columns into a grid
#  grid:  the geometry master
#  what:  row or column
#  index: where to insert
#  count: how many rows/cols to insert
 
proc grid_insert {grid what index {count 1}} {
    foreach slave [grid slaves $grid] {
	array set info [grid info $slave]
	if {$info(-$what) >= $index} {
	    incr info(-$what) $count
	    eval {grid $slave} [array get info]
	} elseif {$info(-$what)+$info(-${what}span) > $index} {
	    incr info(-${what}span) $count
	    eval {grid $slave} [array get info]
	}
    }
}

14. Miscellaneous Tk questions

14.1. How can I get the name of my own interpreter?

tk appname or winfo name . returns the name of your Tk interpreter as seen by others.


14.2. How can I destroy every window except '.'?

The answer is:

eval destroy [winfo children .]

The eval is necessary so that the list of children windows can be separated into individual arguments. Destroy will get individual window names instead of one big string.


14.3. How can I get drag & drop functionality in my program?

The BLT (http://www.tcltk.com/blt/) extension has this functionality.

You can also try the all-tcl code by Donal Fellows at http://www.cs.man.ac.uk/~fellowsd/tcl/.

http://sourceforge.net/projects/tkdnd/ provides native Xdnd and Windows dnd functionality for 8.3.3+.


14.4. How can I get a double-click to ignore a single-click?

In short, you can't. A single-click will always register at least once - in the interval between the clicks of a double-click. Tk does not delay evaluation of a mouse button binding to see if the user will double or triple click. You can prevent a second single-click binding from triggering by adding a break to the end of the double-click binding.


14.5. How can I warp the mouse pointer?

This functionality is provided by Tk's event command in 8.3+. Note it is considered improper to warp the user's cursor in general. Prior to 8.3, you can make a simple dynamically loadable library to do it. Here is the core code:

int
Tk_CursorCmd(clientData, interp, argc, argv)
ClientData clientData;
Tcl_Interp *interp;                 /* Current interpreter. */
int argc;                           /* Number of arguments. */
char **argv;                        /* Argument strings. */
{
  int length;
  char c;
  Tk_Window tkwin = (Tk_Window) clientData;
  Tk_Window winPtr;
 
  if (argc < 2) {
    Tcl_AppendResult(interp, "wrong # args:  should be \"",
                     argv[0], " ?options?\"", (char *) NULL);
    return TCL_ERROR;
  }
 
  length = strlen(argv[1]);
  c = argv[1][0];
  if (c == 'w' && strncmp(argv[1], "warp", length) == 0) {
    int x,y;
    Window win;
 
    if (argc != 5) {
      Tcl_AppendResult(interp, "wrong # args:  should be \"",
                       argv[0], " warp <window> <x> <y>\"", (char *) NULL);
      return TCL_ERROR;
    }
    if ( argv[2][0] == '.' ) {
      winPtr = (Tk_Window ) Tk_NameToWindow(interp, argv[2], tkwin);
      if (winPtr == NULL) {
        return TCL_ERROR;
      }
      win = Tk_WindowId(winPtr);
    } else {
      winPtr = (Tk_Window )clientData;
      win = None;
    }
 
    if (Tk_GetPixels(interp,winPtr,argv[3],&x) != TCL_OK) return TCL_ERROR;
    if (Tk_GetPixels(interp,winPtr,argv[4],&y) != TCL_OK) return TCL_ERROR;
 
    XWarpPointer(Tk_Display(winPtr),None,win,0,0,0,0,x,y);
  }
 
  return TCL_OK;
}

You'll of course need an Foo_Init function with something like:

Tcl_CreateCommand(interp, "cursor", Tk_CursorCmd,
        (ClientData) Tk_MainWindow(interp), NULL);

That will give you a command that understands cursor warp <window> <X> <Y>. The Tk dash patch (http://purl.oclc.org/net/nijtmans/dash.html) also has added this functionality to the Tk event command by adding a -warp option, which is more robust than the above.


14.6. How do I run wish programs without a display?
How do I run my wish program on a server?

At the moment this is not possible in Tk without modifying the code. This feature is on the core ToDo list.


14.7. Is there a difference between stand-alone Tk and the Tk plugin?

Yes. While regular Tk and the Tk plugin (http://www.tcl.tk/software/plugin/) are based off the same source code, the plugin is subtly different due to its web-based interaction. Primarily, the security policies for the plugin remove certain commands from being evaluated in the interpreter (the plugin code is run in a safe interpreter). Also, there are some enhancements to the plugin (as of v2 of the plugin) such as the ability to intercommunicate with other applets or other sites when being run.

The plugin works with Netscape 4.0+ or Microsoft Explorer 5.0+ for Unix, Mac or Windows.


14.8. How can I do terminal emulation in Tk?

Courtesy of Don Libes (libes at nist gov):


15. Questions on Tk related extensions/applications

15.1. What is incrTcl/incrTk?

[incr Tcl] (http://www.tcltk.com/itcl/) provides the extra language support needed to build large Tcl/Tk applications. It introduces the notion of objects, which act as building blocks for an application. Each object is a bag of data with a set of procedures or methods that are used to manipulate it. Objects are organized into classes with identical characteristics, and classes can inherit functionality from one another. This object-oriented paradigm adds another level of organization on top of the basic variable/procedure elements, and the resulting code is easier to understand and maintain.

[incr Tk] (http://www.tcltk.com/itk/) is a framework for building megawidgets using the [incr Tcl] (http://www.tcltk.com/itcl/) object system. Megawidgets are high-level widgets like a file browser or a tab notebook that act like ordinary Tk widgets but are constructed using Tk widgets as component parts, without having to write C code. In effect, a megawidget looks and acts exactly like a Tk widget, but is considerably easier to implement.


15.2. What is BLT?

BLT (http://www.tcltk.com/blt/) is an extension to the Tk toolkit, adding new widgets (like a 2D graph widget), another geometry manager (now subsumed by Tk's grid), and others commands. It does not require any patching of the Tcl or Tk source files. It runs on Windows as well (since v2.4).


15.3. What is Tix?

Tix (http://tix.sourceforge.net/) (Tk Interface Extension) is an extensive set of over 40 megawidgets including ComboBox, Motif style FileSelectBox, MS Windows style FileSelectBox, PanedWindow, NoteBook, Hierarchical List, Directory Tree and File Manager, among others.


15.4. Is there a GUI builder available?
What is XF/Visual Tcl?

There are a few GUI (Graphical User interface) builders available for Tk.

XF is the oldest major GUI builder app for Tcl/Tk and is available at http://www.cimetrix.com/sven/xf.html.

Visual Tcl (not the SCO version of Tcl) is a new GUI builder with some IDE features for Tcl/Tk and is available at http://vtcl.sourceforge.net/.


15.5. Is there a spreadsheet/table widget in Tk?
What is TkTable?

TkTable is a Tk widget extension intended to fill the gap of a table or spreadsheet widget for Tk. It is not a full-fledged spreadsheet, but has all the basic capabilities for making one. It can be found at http://tktable.sourceforge.net/.


15.6. What other languages besides Tcl does Tk work with?
What is this (Perl|Scheme|Guile|.*)/Tk I've heard about?

Tk, as a user interface toolkit, has been grafted onto many other languages. There is an effort underway to develop a Tcl independent Tk for any language to easily adapt Tk as its UI extension. Among the many languages which currently make use of Tk:


16. Reporting bugs, Asking further questions, Other resources

16.1. My question isn't answered here. What do I do now?
What is the netiquette for posting to the newsgroup?

Thanks for looking here first. There are two newsgroups for the Tcl language: news:comp.lang.tcl for basic discussion of bugs, problems and ideas, and news:comp.lang.tcl.announce for announcements of new versions of Tcl/Tk and related applications. Aside from the basic netiquette of posting to newsgroups, the following conventions should be followed:

Pnews on UNIX is the general tool for posting to newsgroups. Netscape 3+ also has facilities to post to a newsgroup if you have the news server preferences set up correctly.

You can also search previous postings to the newsgroup by using the search engine at http://groups.google.com/advanced_group_search?as_ugroup=comp.lang.tcl. Select the power search, create a query filter and specify comp.lang.tcl, then do a find on the topic of interest.

mirror.utcorp.net is a free provider for receiving and posting messages to news:comp.lang.tcl.


16.2. I think I found a bug in Tk. How do I go about reporting it?

In the unlikely event you encounter a bug in Tk, make sure to go through the following process before posting to news:comp.lang.tcl or submitting a bug to Tcl Sources/Bug DB (http://tcl.sourceforge.net/).

  1. Have you isolated the bug to make sure that Tk (or Tk's interaction with something) is directly at fault?
  2. Are you using the most recent version of Tk? If not, make sure that the bug has not already been fixed by the newest version.
  3. The best way to submit a bug (even better with patch) to the Tcl core team is through the URL Tcl Sources/Bug DB (http://tcl.sourceforge.net/). I recommend also posting to news:comp.lang.tcl as there are many experts lurking there who might be able to answer your question without the need to interrupt the core team while they are busy fixing all those bugs.
  4. If you believe it is an extension at fault, see the FAQ for that extension or post to the newsgroup and make sure to include your full Tcl/Tk + extensions setup.


16.3. There's a bug in the FAQ. How do I go about reporting it?

I'm sure that the problem is really the fault of corruption during transmission of the FAQ. However, concerned netizens should report any problems with this FAQ to the maintainer: Jeffrey Hobbs (jeff at hobbs org).


16.4. What documentation can I find online?

There is a lot of raw information available for download about Tk on the net. Here are some references of note:


Go to Tk Usage FAQ Main Page (http://tcl.sourceforge.net/faqs/tk/)

Last generated: Tue Jul 12 03:07:52 PM PDT 2005 by Jeffrey Hobbs (jeff at hobbs org)