Tk provides a set of Tcl commands that create and manipulate widgets. A widget is a window in a graphical user interface that has a particular appearance and behavior. The terms widget and window are often used interchangeably. Widget types include buttons, scrollbars, menus, and text windows. Tk also has a general-purpose drawing widget called a canvas that lets you create lighter-weight items such as lines, boxes, and bitmaps. The Tcl commands added by Tk are summarized at the end of this chapter.
Tk widgets are organized in a hierarchy. To an application, the window hierarchy means that there is a primary window, and inside that window there can be a number of children windows. The children windows can contain more windows, and so on. Just as a hierarchical file system has directories (i.e., folders) that are containers for files and directories, a hierarchical window system uses windows as containers for other windows. The hierarchy affects the naming scheme used for Tk widgets as described later, and it is used to help arrange widgets on the screen.
Widgets are under the control of a geometry manager that controls their size and location on the screen. Until a geometry manager learns about a widget, it will not be mapped onto the screen and you will not see it. Tk has powerful geometry managers that make it very easy to create nice screen layouts. The main trick with any geometry manager is that you use frame widgets as containers for other widgets. One or more widgets are created and then arranged in a frame by a geometry manager. By putting frames within frames you can create complex layouts. There are three different geometry managers you can use in Tk: grid, pack, and place. The Tk geometry managers are discussed in detail in Chapters 20, 21, and 22.
A Tk-based application has an event-driven control flow, like most window system toolkits. The Tk widgets handle most events automatically, so programming your application remains simple. For specialized behaviors, you use the bind command to register a Tcl command that runs when an event occurs. There are lots of events, including mouse motion, keystrokes, window resize, and window destruction. You can also define virtual events, like Cut and Paste, that are caused by different events on different platforms. Bindings are discussed in detail in Chapter 23. Chapter 15 describes I/O events and the Tcl event loop, while Chapter 42 describes C programming and the event loop.
Event bindings are grouped into classes, which are called bindtags. The bindtags command associates a widget with an ordered set of bindtags. The level of indirection between the event bindings and the widgets creates a flexible and powerful system for managing events. You can create your own bindtags and dynamically change the bindtags for a widget to support mode changes in your application.
The basic structure of a Tk script begins by creating widgets and arranging them with a geometry manager, and then binding actions to the widgets. After the interpreter processes the commands that initialize the user interface, the event loop is entered and your application begins running.
Hello, World! in Tk
Our first Tk script is very simple. It creates a button that prints "Hello, World!" to standard output when you press it. Above the button widget is a title bar that is provided by the window manager, which in this case is twm under X windows:
#!/usr/local/bin/wish
button .hello -text Hello \
-command {puts stdout "Hello, World!"}
pack .hello -padx 20 -pady 10The first line identifies the interpreter for the script:
#!/usr/local/bin/wishThis special line is necessary if the script is in a file that will be used like other UNIX command files. Chapter 2 describes how to set up scripts on different platforms.
button .hello -text Hello \
-command {puts stdout "Hello, World!"}=> .hello
The name of the button is .hello. The label on the button is Hello, and the command associated with the button is:
puts stdout "Hello, World!"The pack command maps the button onto the screen. Some padding parameters are supplied so there is space around the button:
pack .hello -padx 20 -pady 10If you type these two commands into wish, you will not see anything happen when the button command is given. After the pack command, though, you will see the empty main window shrink to be just big enough to contain the button and its padding. The behavior of the packer will be discussed further in Chapters 19 and 20.
Tk uses an object-based system for creating and naming widgets. Associated with each class of widget (e.g., Button) is a command that creates instances of that class of widget. As the widget is created, a new Tcl command is defined that operates on that instance of the widget. Example 18-1 creates a button named .hello, and we can operate on the button using its name as a Tcl command. For example, we can cause the button to highlight a few times:
.hello flashOr, we can run the command associated with the button:
.hello invoke=> Hello, World!
Tk has widget classes and instances, but it is not fully object oriented. It is not possible to subclass a widget class and use inheritance. Instead, Tk provides very flexible widgets that can be configured in many different ways to tune their appearance. The resource database can store configuration information that is shared by many widgets, and new classes can be introduced to group resources. Widget behavior is shared by using binding tags that group bindings. Instead of building class hierarchies, Tk uses composition to assemble widgets with shared behavior and attributes.
Each component of a Tk pathname must start with a lowercase letter or a number. Obviously, a component cannot include a period, either. The lower case restriction avoids a conflict with resource class names that begin with an upper case letter. A resource name can include Tk pathname components and Tk widget classes, and case is used to distinguish them. Chapter 25 describes resources in detail.
Store widget names in variables.
Configuring Tk Widgets
Example 18-1 illustrates a style of named parameter passing that is prevalent in the Tk commands. Pairs of arguments specify the attributes of a widget. The attribute names begin with -, such as -text, and the next argument is the value of that attribute. Even the simplest Tk widget can have a dozen or more attributes that can be specified this way, and complex widgets can have 20 or more attributes. However, the beauty of Tk is that you only need to specify the attributes for which the default value is not good enough. This is illustrated by the simplicity of the Hello, World example.
.hello config -background redWidget attributes can be redefined any time, even the text and command that were set when the button was created. The following command changes .hello into a goodbye button:
.hello config -text Goodbye! -command exitWidgets have a cget operation to query the current value of an attribute:
.hello cget -background=> red
You can find out more details about a widget attribute by using configure without a value:
.hello config -background=> -background background Background #ffe4c4 red
The returned information includes the command-line switch, the resource name, the class name, the default value, and the current value, which is last. The class and resource name have to do with the resource mechanism described in Chapter 25. If you only specify configure and no attribute, then a list of the configuration information for all widget attributes is returned. Example 18-2 uses this to print out all the information about a widget:
proc Widget_Attributes {w {out stdout}} {
puts $out [format "%-20s %-10s %s" Attribute Default Value]
foreach item [$w configure] {
puts $out [format "%-20s %-10s %s" \
[lindex $item 0] [lindex $item 3] \
[lindex $item 4]]
}
}
The tables in this book list widget attributes by their resource name.
You need to know these naming conventions if you specify widget attributes via the resource mechanism. The command-line option can be derived from the resource name by mapping it to all lowercase. The primary advantage of using resources to specify attributes is that you do not have to litter your code with attribute specifications. With just a few resource database entries you can specify attributes for all your widgets. In addition, if attributes are specified with resources, users can provide alternate resource specifications in order to override the values supplied by the application. For attributes like colors and fonts, this feature can be important to users. Resource specifications are described in detail in Chapter 25.
The Tk Manual Pages
This book provides summaries for all the Tk commands, the widget attributes, and the default bindings. However, for the absolute truth, you may need to read the on-line manual pages that come with Tk. They provide a complete reference source for the Tk commands. You should be able to use the UNIX man program to read them:
% man buttonThe tkman program provides a very nice graphical user interface to the UNIX manual pages. On the Macintosh platform, the manual pages are formatted into HTML documents that you can find in the HTML Docs folder of the Tcl/Tk distribution. On Windows, the manual pages are formatted into Help documents.
There are a large number of attributes that are common across most of the Tk widgets. These are described in a separate man page under the name options. Each man page begins with a STANDARD OPTIONS section that lists which of these standard attributes apply, but you have to look at the options man page for the description. In contrast, the tables in this book always list all widget attributes.