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:
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.
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.
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.
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:
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.
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".
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.
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.
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.
The above fragment shows the "configure" command changing the text that is
displayed on the button called ".bHello".
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.
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.
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:
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.
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.