Archive-name: tcl-faq/tk/part1 Maintainer: Jeffrey Hobbs <jeff.hobbs@acm.org> Tk 4+ Usage FAQ (Frequently Asked Questions) An HTML version of this FAQ can be found at http://www.cs.uoregon.edu/research/tcl/faqs/tk/ Tk FAQ for Tcl 7.5+ && Tk 4.1+ This FAQ will address commonly asked questions about usage of the Tk Toolkit (version 4.1+). 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. For Tk 3 related questions, see the Tk 3 Usage FAQ (http://www.cs.uoregon.edu/research/tcl/faqs/tk/tk3.txt). This FAQ is posted monthly to news:comp.lang.tcl, comp.answers, and news.answers and can also be obtained from the Tcl FTP archive (206.109.1.6) (ftp://ftp.neosoft.com/pub/tcl/) in the /pub/tcl/FAQ directory. For additional information on Tcl as well as pointers to other documentation and code, see the FAQ maintained by Larry Virden (mailto:lvirden@cas.org): FAQ: news:comp.lang.tcl Tcl Introductory FAQ (http://www.teraform.com/~lvirden/tcl-faq/part1.html) which resides on the Tcl FTP archive (ftp://ftp.neosoft.com/pub/tcl/) as /pub/tcl/FAQ/tcl-faq.part0*. For information on usage of the Tcl programming language, see the posting by Joe Moss (mailto:joe@morton.rain.com): FAQ: news:comp.lang.tcl Tcl Language Usage FAQ (http://www.psg.com/~joem/tcl/faq.html) which resides on the Tcl FTP archive (ftp://ftp.neosoft.com/pub/tcl/) as /pub/tcl/FAQ/tcl-faq-usage. For additional information about using Tk on Windows, see the posting by Eric Johnson (mailto:johnsone@camax.com): FAQ: news:comp.lang.tcl Tk Windows Usage FAQ (http://www.pconline.com/~erc/tclwin.htm) which resides on the Tcl FTP archive (ftp://ftp.neosoft.com/pub/tcl/) as /pub/tcl/FAQ/tk-usage-windows. Comments, suggestions, and contributions to this FAQ are welcomed by Jeffrey Hobbs (mailto:jeff.hobbs@acm.org). *Legend:* + Emphasized_item + *Stand-out item* + "Quoted item" + 'Embedded code' (less than one line) + Multi-line code body ======================================================================== Last generated: Tue Apr 28 11:28:24 MEZ 1998 by Jeffrey Hobbs (http://www.cs.uoregon.edu/~jhobbs/) Tk 4+ Usage FAQ (Frequently Asked Questions) An HTML version of this FAQ can be found at http://www.cs.uoregon.edu/research/tcl/faqs/tk/ Tk FAQ for Tcl 7.5+ && Tk 4.1+ This FAQ will address commonly asked questions about usage of the Tk Toolkit (version 4.1+). 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. For Tk 3 related questions, see the Tk 3 Usage FAQ (http://www.cs.uoregon.edu/research/tcl/faqs/tk/tk3.txt). This FAQ is posted monthly to news:comp.lang.tcl, comp.answers, and news.answers and can also be obtained from the Tcl FTP archive (206.109.1.6) (ftp://ftp.neosoft.com/pub/tcl/) in the /pub/tcl/FAQ directory. For additional information on Tcl as well as pointers to other documentation and code, see the FAQ maintained by Larry Virden (mailto:lvirden@cas.org): FAQ: news:comp.lang.tcl Tcl Introductory FAQ (http://www.teraform.com/~lvirden/tcl-faq/part1.html) which resides on the Tcl FTP archive (ftp://ftp.neosoft.com/pub/tcl/) as /pub/tcl/FAQ/tcl-faq.part0*. For information on usage of the Tcl programming language, see the posting by Joe Moss (mailto:joe@morton.rain.com): FAQ: news:comp.lang.tcl Tcl Language Usage FAQ (http://www.psg.com/~joem/tcl/faq.html) which resides on the Tcl FTP archive (ftp://ftp.neosoft.com/pub/tcl/) as /pub/tcl/FAQ/tcl-faq-usage. For additional information about using Tk on Windows, see the posting by Eric Johnson (mailto:johnsone@camax.com): FAQ: news:comp.lang.tcl Tk Windows Usage FAQ (http://www.pconline.com/~erc/tclwin.htm) which resides on the Tcl FTP archive (ftp://ftp.neosoft.com/pub/tcl/) as /pub/tcl/FAQ/tk-usage-windows. Comments, suggestions, and contributions to this FAQ are welcomed by Jeffrey Hobbs (mailto:jeff.hobbs@acm.org). *Legend:* + Emphasized_item + *Stand-out item* + "Quoted item" + 'Embedded code' (less than one line) + Multi-line code body ======================================================================== Here is the list of questions. You can search for the corresponding answer by searching for the question number. For example, searching for "#3.1." will get you that answer. **** Building and Installing Tk et_al on my system **** #1.1. Are there binaries available for my system? #1.2. How do I get Tcl/Tk to compile/work on my machine? #1.3. Why does the link step says that some of the functions Tcl needs are missing when I am trying to build it? #1.4. How do I add BLT to a Tcl(X)/Tk? #1.5. How do I create a dynamically loadable library for Tcl/Tk? #1.6. Where are the '.lib' files for building shared libraries on Windows? **** Running Tk applications **** #2.1. Where can I get info on porting my Tk3 application to Tk4? to Tk8? #2.2. How do I get my wish application to execute on Unix (I just get a wish prompt!)? #2.3. How do I run Tcl/Tk scripts by double-clicking on Windows/Mac? #2.4. How can I get Tk to use 'send' (I get security error messages)? Does 'send' work on Windows/Mac? #2.5. How can I ignore send from other applications? #2.6. Does Tcl/Tk read a resource/startup file? #2.7. How can I call Tk scripts from a C program? #2.8. Why does Tk look funny in CDE/VUE? **** Tk application bindings (mouse and keyboard) **** #3.1. How can I change the default class bindings? #3.2. How can I delete a binding? #3.3. How can I bind to the arrow keys? #3.4. How can I get window manager's mouse bindings to work in my Tk application? #3.5. How can I add new actions to an existing binding? #3.6. How do the mouse buttons map when I have less than 3 buttons? **** Tk user interface questions **** #4.1. How can I set X11 resources for a wish application in an app-defaults file? #4.2. Can I choose a particular user interface look and feel? How do I get native look and feel on Windows/Mac? #4.3. How can I change the Tk cursor? #4.4. How can I change the default colors in Tk? #4.5. How do I specify fonts in Tk? **** Tk window manager interaction questions **** #5.1. How can I get the geometry of my window (I get 1x1+0+0)? #5.2. How can I raise or lower a window? #5.3. How can I withdraw/iconify a window? How can I remap a withdrawn window? #5.4. How can I use Tk in a subwindow of a non-Tk application? #5.5. How can I mix interactions between Xt and Tk/Tcl? #5.6. How can I bind the ResizeRequest event? #5.7. What is the difference between wm and winfo? #5.8. How can I prevent my toplevel from being destroyed? How do I make my toplevel ignore the window manager delete button? #5.9. How can I prevent my toplevel from being iconified? #5.10. How can I keep my toplevel on top? #5.11. Is Tk fully ICCCM compliant? **** Tk 'canvas' widgets questions **** #6.1. How can I get output from a Tk canvas? #6.2. How can I fill a canvas area which is bounded by lines as opposed to a shape like a polygon, oval, etc.? #6.3. How can I raise/lower canvas window objects or draw graphics onto a window object inside a canvas? #6.4. How can I detect when the canvas has been resized? #6.5. How can I use a list of coordinates in a variable to create a polygon (or any other item)? #6.6. How can I speed up 'canvas' performance? #6.7. How can I put/print an image on the 'canvas'? #6.8. Why doesn't the 'canvas' seem to start at 0,0? #6.9. Does the 'canvas' have a 'see' method? **** Tk 'entry' widgets questions **** #7.1. How can I initialize an entry widget with some text? #7.2. How can I limit entry widget input (length or type of chars)? **** Tk 'listbox' widgets questions **** #8.1. How can I select multiple items that are not adjacent in the listbox at one time? #8.2. How can I select items in more than one Tk listbox at a time? #8.3. How can I avoid fractional white space at the end of a resizable listbox? #8.4. How can I scroll multiple listboxes with one scrollbar? #8.5. Why doesn't '.listbox curselection' or 'selection get' return the proper item when I make a button binding to my listbox? #8.6. Can I have different colored lines in a listbox? **** Tk 'menu' widget questions **** #9.1. How can I get the tearoff menu to reflect changes in the regular menu? #9.2. Why do I have problems accessing item/index 0 of my menu? #9.3. How do know when I am over a specific entry in a menu? **** Tk 'text' widgets questions **** #10.1. How can I pack a text widget so that it can be resized interactively? #10.2. Why do I get an extra newline from the text widget? #10.3. How can I check to see if the text widget contents have changed? #10.4. How can I maintain read-only sections of a text widget? #10.5. Is there an overwrite/overstrike mode for text/entry widget? #10.6. How can I always see the end of the text widget? #10.7. Does the text widget have undo? **** Miscellaneous Tk widget questions **** #11.1. How can I create a scrollable window of buttons? #11.2. How can I create a widget with an upper case name? #11.3. How can I vertically align radio/check buttons regardless of font? #11.4. How can I group a set of radiobuttons together? **** Tk image questions **** #12.1. Does Tk support JPEG/GIF/XPM/etc? #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? #12.3. How do I get Tk to recognize the transparency in my GIF images? #12.4. How can I get bitmaps created with 'image' to work with '-stipple'? **** Tk geometry manager questions **** #13.1. How can I find my invisible windows when using the packer? #13.2. How can I get 'cget' to return the correct size of a resized widget? ('.widget cget -width|height' returns the wrong size!) #13.3. How can I add a row/col to the grid? **** Miscellaneous Tk questions **** #14.1. How can I get the name of my own interpreter? #14.2. How can I destroy every window except '.'? #14.3. How can I get drag & drop functionality in my program? #14.4. How can I get a double-click to ignore a single-click? #14.5. How can I warp the mouse pointer? #14.6. How do I run wish programs without a display? How do I run my wish program on a server? #14.7. Is there a difference between stand-alone Tk and the Tk plugin? #14.8. How can I do terminal emulation in Tk? **** Questions on Tk related extensions/applications **** #15.1. What is incrTcl/incrTk? #15.2. What is BLT? #15.3. What is Tix? #15.4. Is there a GUI builder available? What is SpecTcl/XF/Visual Tcl? #15.5. Is there a spreadsheet/table widget in Tk? What is TkTable? #15.6. What other languages besides Tcl does Tk work with? What is this (Perl|Scheme|Guile|.*)/Tk I've heard about? **** 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? #16.2. I think I found a bug in Tk. How do I go about reporting it? #16.3. There's a bug in the FAQ. How do I go about reporting it? #16.4. What documentation can I find online? *** *** Questions and Answers *** ** * 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 the Macintosh and Windows platforms at: Windows: ftp://ftp.sunlabs.com/pub/tcl/win(version).exe Macintosh: ftp://ftp.sunlabs.com/pub/tcl/mactk(version).sea.hqx and mirrored at: ftp://ftp.neosoft.com/pub/tcl/mirror/ftp.smli.com/ The binaries are self-extracting archives. Run the program to install Tcl/Tk. The sources are freely available from the same places. You can pay a nominal fee for precompiled UNIX binaries. See http://sunscript.sun.com/TclTkCore/ for more information. See the Tcl Home Page (http://sunscript.sun.com/) for a listing of the newest available versions. ======================================================================== #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@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? The team at Sun have provided examples for building a dynamically loadable library for any supported Tk platform. You can find this at ftp://ftp.sunlabs.com/pub/tcl/example.{zip,tar.gz,tar.Z}. ======================================================================== #1.6. Where are the '.lib' files for building shared libraries on Windows? They are distributed separate from the binaries and sources, but in the same FTP places: ftp://ftp.sunlabs.com/pub/tcl/vclibs(version).zip ftp://ftp.neosoft.com/pub/tcl/mirror/ftp.smli.com/vclibs(version).zip ======================================================================== ** * 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://www.sunlabs.com/research/tcl/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://sunscript.sun.com/TclTkCore/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/somethingbig/bin/sun4/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 Windows95/NT, 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\wish80.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 supported on the Mac or Windows platforms as of Tk8.1. ======================================================================== #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@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. Sun has created some basic examples for all platforms at ftp://ftp.sunlabs.com/pub/tcl/example.{zip,tar.gz,tar.Z}. ======================================================================== #2.8. Why does Tk look funny in CDE/VUE? The problem is that this idiotically 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 ======================================================================== ** * 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 the Mac, ??? 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>'). ======================================================================== ** * 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. ======================================================================== #4.3. How can I change the Tk cursor? On Unix, the file "/usr/include/X11/cursorfont.h" for a list of available cursors. You can use the names in there by removing the 'XC_'. These same cursors are emulated on Windows/Mac. On the Mac you can also use crsr and CURS style cursors by the name of the resource. 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 {$list != ""} { set next {} foreach w $list { set class [winfo class $w] set cursor [lindex [$w config -cursor] 4] if {[winfo toplevel $w] == $w || $cursor != ""} { lappend busy [list $w $cursor] } set next [concat $next [winfo children $w]] } set list $next } foreach w $busy { catch {[lindex $w 0] config -cursor watch} } update idletasks set error [catch {uplevel eval [list $cmds]} result] set ei $errorInfo foreach w $busy { catch {[lindex $w 0] config -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 config -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 config -font {Courier 12 {}} .widget config -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. ======================================================================== ** * 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 -f 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 -f 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@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 (gi0570@rh0015.roma.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. ======================================================================== #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 } } It's been reported that Windows doesn't report '<Visibility>', 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] } } ======================================================================== #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] ======================================================================== ** * 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. Unfortunately this does not currently work for images in the canvas. To get better postscript support, as well as a generally enhanced canvas, get the Tk dash patch (http://www.worldaccess.nl/~nijtmans/dash.html) by Jan Nijtmans (mailto:nijtmans@worldaccess.nl). ======================================================================== #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. ======================================================================== #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://www.worldaccess.nl/~nijtmans/dash.html) by Jan Nijtmans (mailto:nijtmans@worldaccess.nl) has many canvas improvements, including one or two that can improve performance in some situations. ======================================================================== #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 Unfortunately Tk does not yet support the printing of images. You can get this functionality by grabbing the Tk dash patch (http://www.worldaccess.nl/~nijtmans/dash.html) by Jan Nijtmans (mailto:nijtmans@worldaccess.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 config -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 [string match {} $box] return if [string match {} [$c cget -scrollreg]] { ## 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 -scrollreg] { 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 } } ======================================================================== ** * 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 comp {} $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://sunscript.sun.com/products/plugin.html) at http://www.cs.uoregon.edu/research/tcl/code/tclet/entrylimit.html. ======================================================================== ** * 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 ".s set" -relief sunken -bd 2 scrollbar .s -command ".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 {.lb0 .lb1 .lb2 .lb3} proc LBset args { global BOXES foreach lb $BOXES { eval $lb $args } } 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 { listbox $lb -exportsel no -selectmode browse -yscrollcommand LBscroll pack $lb -side left -fill both -expand 1 bind $lb <ButtonPress-1> { LBset select clear 0 end LBset select set [%W nearest %y] } bind $lb <B1-Motion> { LBset select clear 0 end LBset select set [%W nearest %y] LBset see [%W nearest %y] } bind $lb <ButtonRelease-1> { LBset select clear 0 end LBset select set [%W nearest %y] } } 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 not possible with the standard Tk4 'listbox'. Some attempts have been made to make megawidget listboxes with this functionality based on the 'text' or 'canvas' widget. The Tix (http://www.xpi.com/tix/) megawidget extension provides an extended listbox. ======================================================================== ** * 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 'menu's. 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>'. ======================================================================== ** * 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 columnconfig 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? If you want the entire text widget to be read-only, set the "-state" option of the 'text' widget to "disabled". 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 config 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 comp {} [lindex $args 2]] { if {[string comp {} [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 {($s == "") || ([$w cget -state] == "disabled")} { 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 {$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. ======================================================================== #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 does not have a built-in core undo functionality, but it is possible to create such in Tcl. 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://www.dejanews.com/. ======================================================================== ** * 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 "Button $i" -width 10 -command "puts {$i pressed}" .c create window $x $y -window .c.b$i -anchor nw incr y [winfo reqheight .c.b$i] } .c config -scrollregion "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. During a recent revision of Tk, things were changed so that names beginning with a capital letter are reserved for class names. 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 ======================================================================== ** * 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'. Currently only PPM and XBM support the '-data' option. The Tk Image Extension (ftp://ftp.nici.kun.nl/pub/nici/software/tcltk/img/) by Jan Nijtmans (mailto:nijtmans@worldaccess.nl) contains format handlers for XBM, XPM, JPEG, GIF89, PNG and TIFF and the 'pixmap' image type adopted from Tix (http://www.xpi.com/tix/). Further image formats can be added via DLLs with the Tk C command 'Tk_CreateImageType' (along with code to read that format, of course). ======================================================================== #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://sunscript.sun.com/products/plugin.html) and Tk8.0+ can read base64 encoded GIF data via '-data', but this isn't available in Tk4.2- unless you get the excellent Tk plus patch (http://www.worldaccess.nl/~nijtmans/plus.html) by Jan Nijtmans (mailto:nijtmans@worldaccess.nl). ======================================================================== #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 config -image x Donal Fellows has a minimal C extension to support real transparency at http://r8h.cs.man.ac.uk:8000/tcl/transPhoto.c Tk8 removes the need for this hack, properly implementing transparency in GIF images (some bugs may still exist). ======================================================================== #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 Sun's ToDo list. ======================================================================== ** * 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@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 config -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. ======================================================================== #13.3. 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] } } } ======================================================================== ** * 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://r8h.cs.man.ac.uk:8000/tcl/. ======================================================================== #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 not provided by Tk (it's considered improper to warp the user's cursor in general). However, 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://www.worldaccess.nl/~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 Sun's 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://sunscript.sun.com/products/plugin.html) 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. See the Tk Plugin FAQ (http://sunscript.sun.com/techcorner/faq.html) for more information. The plugin works with Netscape 3.0+ or Microsoft Explorer 3.0+ for Unix, Mac or Windows. ======================================================================== #14.8. How can I do terminal emulation in Tk? Courtesy of Don Libes (mailto:libes@nist.gov): + Tk has no built-in terminal widget. There have been a few attempts at making a terminal widget as a Tk extension but none of these implementations have been maintained (i.e., are available for the current version of Tk). This isn't surprising since all of them had significant limitations and it's not clear that this was a sensible approach in the first place. + Borrow an external terminal emulator. In particular, you can use TkSteal to control an xterm. You can also control an xterm with Expect (http://expect.nist.gov/). With TkSteal, your xterm physically appears inside the Tk application. And you can send X events to the emulator just like the user. In contrast, Expect gives you control of the backend of the emulator - so you can make the terminal display what you want, rather than being restricted to the output of some existing program. Similarly, when the user enters keystrokes, you can read them and decide if you want to handle them or pass them on to another program. If you want control of both the user interface and the backend, you can use both TkSteal and Expect together. + Emulate a terminal using a text widget. You can do dumb terminal emulation by using Expect's 'expect_before' command to match characters and insert them into the widget. Expect's tkterm example performs smart terminal emulation. It's capable of handling emacs, vi, or any termcap/terminfo/curses-based program. And since it's done with a text widget, you can manipulate the display simply by accessing the text widget. Exploring_Expect http://www.ora.com/www/item/expect.html covers both dumb and smart terminal emulation in the Tk chapter. ======================================================================== ** * 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. A patch to get BLT (http://www.tcltk.com/blt/) running on Windows or the latest Tk is available at http://www.jessikat.demon.co.uk/. ======================================================================== #15.3. What is Tix? Tix (http://www.xpi.com/tix/) (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 SpecTcl/XF/Visual Tcl? There are a few GUI (Graphical User interface) builders available for Tk. The most recent entrant is SpecTcl (http://sunscript.sun.com/products/spectcl.html), in development by the guys at Sun (see the Tcl Home Page (http://sunscript.sun.com/)), which can output Perl, Tcl or Java UI code and is 'grid' based. 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://www.neuron.com/stewart/vtcl/. ======================================================================== #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://www.cs.uoregon.edu/research/tcl/capp/. ======================================================================== #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: + Tcl Ada Shell (http://www.ocsystems.com/xada/tash/) + Guile/Tk docs (http://nis-www.lanl.gov/~rosalia/mydocs/guile-programmer_2.html) + Oz and Tk (http://www.isg.sfu.ca/oz/#tk) + Perl/Tk FAQ (http://w4.lns.cornell.edu/~pvhp/ptk/ptkTOC.html) + Prolog and Tk (http://www.athena.auth.gr/doc/eclipse/html/protcl.html) + Python and Tk (http://www.python.org/doc/life-preserver/) + Scheme/Tk FAQ (http://ltiwww.epfl.ch/~furrer/STk/FAQ.html) ======================================================================== ** * 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: + Don't make the subject just "Help", start questions with "[Q]": and write a one-liner (<70 chars) that makes sense. + Include the version of Tcl/Tk you are using + Include the OS you are using + If you compiled it yourself, include the name and version of the compiler + Be as detailed, but brief, as possible with your question. Don't just send across a 100 line script and ask what's wrong. Try and narrow down the problem as much as possible. + Include error messages AND the lines that caused them. Sometimes it is not necessary to include the entire error message. Try and parse it down as much as possible without losing relevant information. + Lurk. Lurkers are good on Q&A groups such as news:comp.lang.tcl because very few questions are original. + Make sure to include your email address so respondants can CC: you in email. This is the best way to prevent lost messages and question reposts. The reverse is true for respondents - don't forget to CC: the person as well as make a follow-up to the newsgroup. '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://www.dejanews.com/. Select the power search, create a query filter and specify comp.lang.tcl, then do a find on the topic of interest. ======================================================================== #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. 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 Certain it's a bug? Don't send directly to mailto:bugs@scriptics.com unless you are 99.9% certain. Instead, post to news:comp.lang.tcl. There are many experts lurking there who might be able to answer your question without the need to interrupt Dr. John & co. while they are busy fixing all those bugs. 4 Start the subject line with "BUG:" and make the subject relevant to the bug within a 70 character limit. 5 If you have a patch, use "PATCH:" and also send to mailto:patches@scriptics.com. 6 Include a brief script (10-20 lines) that reproduces the problem if possible. Make sure it doesn't rely on extensions or site-specific info. 7 Explain how to reproduce the bug (press_button_X_...) if necessary, and what you were expecting to occur. 8 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 (mailto:jeff.hobbs@acm.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: + Tcl Home Page (http://sunscript.sun.com/) + Tcl/Tk man pages (http://sunscript.sun.com/man/) in HTML + Tk quick reference guide (ftp://ftp.slac.stanford.edu/software/TkMail/tkref-4.1.0.tar.gz) + Tcl WWW archive (http://www.neosoft.com/tcl/) + Tcl Introductory FAQ (http://www.teraform.com/~lvirden/tcl-faq/part1.html) + Tcl Language Usage FAQ (http://www.psg.com/~joem/tcl/faq.html) + Tk Windows Usage FAQ (http://www.pconline.com/~erc/tclwin.htm) ======================================================================== Last generated: Tue Apr 28 11:28:26 MEZ 1998 by Jeffrey Hobbs (http://www.cs.uoregon.edu/~jhobbs/) -- Jeffrey Hobbs "I'm really just a Tcl-bot" jeff.hobbs at acm.org | Jeffrey.Hobbs at oen.siemens.de
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |