The tk shell


Topics

Introduction
A first application
Object packing and frames
General widget options
Some useful widgets

Introduction

Tk is an extension to tcl which introduces a variety of new commands which allow the programmer to easily interface with the X environment. Instead of working with text based programs, the user can now experience a graphical user interface.

The tk toolkit uses a different shell than tclsh, it is called wish. This shell can be accessed in much the same way as the tclsh, with the first line in the script file looking similar to the following:

#!/.software/local/.admin/bins/bin/wish
Everything after this line is just like a tcl script.

The tk toolkit is based around widgets, which is the X terminology for a visual component. Typical widgets are buttons, text labels, entry boxes, and menus. Tk supports all of these and more. The widgets in tk have a command associated with them, and this command allows the creation of the widget as well as some configuration. All widgets must be named, and the name must begin with a "." followed by a lower case character. The creation of a widget essentially creates a new procedure with the name of the widget that can then be called on to configure the created object. All of this is much more clear with a few examples, so instead of going through all of this in a tedious manner, we will write a couple of mini-applications.

Back to the top


A first application

What would a programming guide be without a "hello world" example? The following code creates a window with the title "hey there", and a button that says "hello world". Pressing the button results in the application closing. The following code contains everything needed to get you started, bear in mind the first line should have the location of your wish shell.

#!/.software/local/.admin/bins/bin/wish

wm title . "hey there"

button .bHello -text "hello world" -command exit
pack .bHello
So how does all of this work? The first command encountered here is "wm", this is short for window manage. It takes a few arguments, the first of which specifies what sub-command we want to run. Our sub-command is "title", this is the command that you run when you want to change the text that appears in the title bar of the application. The "." symbol is a tk short form for the root window. The root window is the window that the rest of the application is built on top of. The "." window is always defined.

The "button" command is our first widget operator. As would be expected this operator creates a button widget. Note that the button is not placed when it is created, it is just created. The first argument to the "button" command is the name of the button we want to create. Our button is ".bHello". All widget names must begin with a "." and a small letter. The "." denotes that this is a child of the root window. The remaining arguments are for the widget to interpret. The "-text" option allows the programmer to specify what text shows up on the button. The "-command" option specifies the name of a procedure to call when the button is pressed. The "exit" command is built into tcl/tk, and it causes the program to close.

The pack operator is what is called a geometry manager. It takes a list of widgets and places them on the screen. If the programmer doesn't specify otherwise then the objects are placed in from top to bottom in the root window in the order that they were given to pack. The pack operator has many options to allow you to specify how things should be arranged, these will be discussed in the section on packing and frames .

From here on in the code is only going to come in fragments. The example above that specified the wish shell, and the "wm" command are typically common to all tk applications.

Back to the top


Object packing and frames

The above section introduced the "pack" key-word. Before getting into more detail on positioning widgets using "pack" it is wise to introduce the concept of a frame. A frame is an invisible widget which acts as a container for other widgets. You create a frame with the "frame" command, and like other widgets specify a name to refer to it by later. To illustrate the use of frames and packing things lets try to build a telephone key pad using button widgets.

To create a telephone key pad we need four rows of buttons, with each row containing three buttons. The following example creates a few of these buttons:

button .b1 -text "1"
button .b2 -text "2"
button .bpnd -text "#"
So how do we get the rows? If you issue a pack .b1 .b2 ... .bpnd then all of the buttons will appear one on top of each other. The answer is frames. A frame can be created for each row, and the buttons can be packed into the frame. The four frames can then be packed normally, one on top of each other. The following example creates a row full of buttons and packs them into a frame.
frame .fRow1
button .b1 -text "1"
button .b2 -text "2"
button .b3 -text "3"
pack .b1 .b2 .b3 -in .fRow1
This gives us a row of buttons in the frame. The frame is not yet displayed since we haven't packed it. The following command would pack four frames named ".fRow1", ".fRow2", ".fRow3", and ".fRow4".
pack .fRow1 .fRow2 .fRow3 .fRow4

Options for the "pack" command

You have already seen the "-in" option for the "pack" command, the following is a list of other options and a short description of each.

-after widget
allows you to specify that this object should appear after the one named widget
-anchor position
allows you to specify relative positioning, defaults to "center", others available are "n", "ne", "e", "se", "s", "sw", "w", and "nw" where each is an abbreviation for the cardinal compass points
-before widget
allows you to specify that this object should appear before the one named widget
-expand boolean
if boolean is true this widget will expand to fill in any empty space which is around it; extra space can occur due to sizing of the window; defaults to false
-fill style
specifies how to grow the widget if there is extra space; defaults to "none", other options are "x", "y", and "both"
-in frame
allows you to put widgets in the object called frame
-ipadx distance
specifies internal padding of the x axis for the widget
-ipady distance
specifies internal padding of the y axis for the widget
-padx distance
specifies external padding of the x axis for the widget
-pady distance
specifies external padding of the y axis for the widget
-side side
specifies which side the widget should be packed against; defaults to "top"; can be "left", "right", "top", or "bottom"

Back to the top


General widget options

Most widgets have a series of options common to all of them. These common options control attributes like size and colour. Anywhere where a measurement is used in conjunction with these options the number can be suffixed by a letter indicating the unit of measurement. The units default to pixels, which is the "p" suffix. Other available suffixes are "c" (centimetres), "i" (inches), and "m" (millimetres). The following explains some of the options available to most widgets.

-width measure
-height measure
specifies the width or height of the widget; normally specified in the above mentioned units, although some widgets that use text measure in number of characters
-relief type
specifies the appearance of the widget; options are "raised", "sunken", "flat", "groove", and "ridge"
-borderwidth measure
specifies the width of a border if one is created by the "-relief" command
-fg colour
-bg colour
fore and background colours; can be specified using a string or a series of RGB values; available colours depend on the X installation; most basic colours are available on most systems: "RED", "BLUE", "BLACK", etc.
-text text
specify the text that shows up on the widget
-textvariable varname
associates the variable varname with the text on the widget; the text on the widget always shows what the contents of the variable are

The "configure" command

The introduction mentioned that once a widget is created there is a procedure associated with it in order for the programmer to manipulate the widget after it has been created. This manipulation is done via the "configure" command. Any option that is valid for the widget can be specified after the "configure" command. The "configure" key-word shows up after the name of the widget, just like a procedure.

button .bHello -text "Hello"
pack .bHello
.bHello configure -text "Hi"
The above fragment shows the "configure" command changing the text that is displayed on the button called ".bHello".

Back to the top


Some useful widgets

Buttons, checkbuttons, and radiobuttons

The button widget has mostly been covered by the previous examples. The checkbutton and radiobutton widgets are similar, but have some options which are specific to them. Both of these widgets have a "-variable" option, where the name of a variable can be specified and this variable will contain a truth value reflecting whether or not the check/radiobutton is selected. Radiobuttons are grouped together to allow mutually exclusive selection. This grouping is obtained by each having the same variable specified in the "-variable" option. The radiobuttons also have an additional parameter called "-value" which is the value that the variable should get upon selection. The following piece of code allows the user to select a single font.

radiobutton .rb1 -text "Times" -variable font -value "times"
radiobutton .rb2 -text "Courier" -variable font -value "courier"
radiobutton .rb3 -text "Symbol" -variable font -value "symbol"
pack .rb1 .rb2 .rb3
The above example would put three radio buttons with text labels on the screen. Only one of these radiobuttons can be selected at a time. When a selection is made the text following "-value" is put in the variable called "font". If the "Times" button is selected then the variable "font" gets "times" put into it.

Labels

The label widget is relatively simple, its sole job is to display text. This widget uses the "-text" or "-textvariable" option to specify the text that is to be displayed. An example is:

label .lLabel -text "This is a text label"
pack .lLabel

Entry Fields

So far we have been displaying data, what if we want some user input? The entry widget is a text entry field where the user can type information. Most of the regular options apply for the entry field, with a minor modification, the "-textvariable" now specifies the name of the variable that will contain what is typed in the entry field.

entry .eInput -width 20 -textvariable input
pack .eInput
This example creates an entry widget called ".eInput", with a width of twenty characters. The variable "input" will be updated to reflect the contents of the entry field.

Back to the top