1.2 "Hello, World!" with Tk
Tcl provides a full set of programming features such as variables, loops, and procedures. It can be used by itself or with extensions that implement their own Tcl commands in addition to those in the Tcl core.
One of the more interesting extensions to Tcl is the set of windowing commands provided by the Tk toolkit. Tk's commands allow you to create graphical user interfaces. Many of the examples in this book use an application called wish ("windowing shell"), which is similar to tclsh except that it also includes the commands defined by Tk. If Tcl and Tk have been installed on your system, you can invoke wish from your terminal or command prompt window just as you did for tclsh; it displays a small empty window on your screen and then reads commands from the console. Alternatively, if you have Tcl/Tk version 8.4 or later installed, you can invoke the tclsh application, and then use the command package require Tk to dynamically load the Tk extension.
Here is a simple Tk script that you could run with wish:
button .b -text "Hello, world!" -command exit grid .b
If you enter these two Tcl commands in wish, the window's appearance changes to that shown in Figure 1.1. If you move the pointer over the "Hello, world!" text and click the main mouse button (the leftmost button in most configurations), the window disappears and wish exits.
Figure 1.1 The "Hello, world!" application
Several things about this example need explanation. First let us deal with the syntactic issues. The example contains two commands, button and grid, both of which are implemented by Tk. Although these commands do not look like the expr command in the previous section, they have the same basic structure as all Tcl commands: one or more words separated by whitespace characters. The button command contains six words, and the grid command contains two words.
The fourth word of the button command is enclosed in double quotes. This allows the word to include whitespace characters; without the quotes, Hello, and world! would be separate words. The double quotes are delimiters, not part of the word itself; they are removed by the Tcl interpreter before the command is executed.
For the expr command the word structure doesn't matter much since expr concatenates all its arguments. However, for the button and grid commands, and for most Tcl commands, the word structure is important. The button command expects its first argument to be the name of a new window to create. Additional arguments to this command must come in pairs, where the first argument of each pair is the name of a configuration option and the second argument is a value for that option. Thus if the double quotes were omitted, the value of the -text option would be Hello, and world! would be treated as the name of a separate configuration option. Since there is no option defined with the name world! the command would return an error.
Now let us move on to the behavior of the commands. The basic building block for a graphical user interface in Tk is a widget. A widget is a window with a particular appearance and behavior (the terms widget and window are used synonymously in Tk). Widgets are divided into classes such as buttons, menus, and scrollbars. All the widgets in the same class have the same general appearance and behavior. For example, all button widgets display a text string, bitmap, or image and execute a Tcl script when the user clicks the button.
Widgets are organized hierarchically in Tk, with names that reflect their positions in the hierarchy. The main widget, which appeared on the screen when you started wish, has the name . and .b refers to a child b of the main widget. Widget names in Tk are like file name paths except that they use . as a separator character instead of / or \. Thus, .a.b.c refers to a widget that is a child of widget .a.b, which in turn is a child of .a, which is a child of the main widget.
Tk provides one command for each class of widgets, called a class command, which you invoke to create widgets of that class. For example, the button command creates button widgets. This is similar to standard object-oriented programming principles, though Tk doesn't support direct subclassing of the widget classes. All of the class commands have the same form: the first argument is the name of a new widget to create, and additional arguments specify configuration options. Different widget classes support different sets of options. Widgets typically have many options, with default values for the options that you don't specify. When a class command like button is invoked, it creates a new widget with the given name and configures it as specified by the options.
The button command in the example specifies two options: -text, which is a string to display in the button, and -command, which is a Tcl script to execute when the user invokes the button. In this example the -command option is exit. Here are a few other button options that you can experiment with:
- -background—the background color for the button, such as blue
- -foreground—the color of the text in the button, such as black
- -font—the font to use for the button, such as "times 12" for a 12-point Times Roman font
Creating a widget does not automatically cause it to be displayed. The grid command causes the button widget to appear on the screen. Independent entities called geometry managers are responsible for computing the sizes and locations of widgets and making them appear on the screen. The separation of widget creation and geometry management provides significant flexibility in arranging widgets on the screen to design your application. The grid command in the example asks a geometry manager called the gridder to manage .b. The gridder arranges widgets in a grid of columns and rows. In this case, the command placed .b in the first column of the first row of the grid and sized the grid to just large enough to accommodate the widget; furthermore, if the parent has more space than needed by the grid, as in the example, the parent is shrunk so that it is just large enough to hold the child. Thus, when you entered the grid command, the main window (.) shrank from its original size to the size that appears in Figure 1.1.