10.38.3.4 Widget Creation

As has already been said, a widget is a window object that has state and behavior. In terms of Tcl/Tk a widget is created by calling a widget creation command. There is a specific widget creation for each type of widget.

The widget creation command is supplied with arguments. The first argument is always the name you want to give to the resulting widget; the other arguments set the initial state of the widget.

The immediate result of calling a widget creation command is that it returns the name of the new widget. A side-effect is that the instance of the widget is created and its name is defined as in the Tcl interpreter as a procedure through which the widget state can be accessed and manipulated.

This needs an example. We will use the widget creator command button to make a button widget:

     button .fred -text 'Fred' -background red

which creates an instance of a button widget named .fred that will display the text Fred on the button and will have a red background color. Evaluating this command returns the string .fred, the name of the newly created widget.

As a side-effect, a Tcl procedure named .fred is created. A call to a widget instance has the following form:

     widgetName method methodArgs

where widgetName is the name of the widget to be manipulated, method is the action to be performed on the widget, and methodArgs are the arguments passed to the method that is performed on the widget.

The two standard methods for widgets are configure and cget. configure - is used to change the state of a widget; for example:

     .fred configure -background green -text 'Sid'

will change the background color of the widget .fred to green and the text displayed to Sid.

cget is used to get part of the state of a widget; for example:

     .fred cget -text

will return Sid if the text on the button .fred is Sid.

In addition to these general methods, there are special methods for each widget type. For example, with button widgets you have the flash and invoke methods.

For example,

     .fred invoke

can be called somewhere in the Tcl code to invoke button .fred as though it had been clicked on.

     .fred flash

can be called somewhere in the Tcl code to cause the button to flash.

We will come across some of these special method when we discuss the widgets in detail. For a comprehensive list of widget methods, refer to entry for the appropriate widget creation command in the Tcl/Tk manual.

We now discuss the widget creation command for each widget type.

A label is a simple widget for displaying a single line of text. An example of creating an instance of a label is

     label .l -text "Hello world!"

which simply creates the label named .l with the text `Hello world!' displayed in it. Most widgets that display text can have a variable associated with them through the option -textvariable. When the value of the variable is changed the text changes in the associated label. For example,

     label .l -text "Hello world!" -textvariable mytext

creates a text label called .l displaying the initial text `Hello world!' and associated text variable mytext; mytext will start with the value `Hello world!'. However, if the following script is executed:

     set mytext "Goodbye moon!"

the text in the label will magically change to `Goodbye moon!'.

A message widget is similar to a label widget but for multi-line text. As its name suggests it is mostly used for creating popup message information boxes.

An example of a message widget is

     message .msg -text "Your data is incorrect.\n\n \
                   Please correct it and try again." \
         -justify center

which will create a message widget displaying the text shown, center justified. The width of the message box can be given through the -width switch. Any lines that exceed the width of the box are wrapped at word boundaries.

Calling the button command creates an instance of a button widget. An example is:

     button .mybutton -text "hello" -command {puts "howdie!"}

which creates a button with name .mybutton that will display the text "hello" and will execute the Tcl script puts "howdie!" (that is print howdie! to the terminal) when clicked on.

Checkbuttons are buttons that have a fixed state that is either on or off. Clicking on the button toggles the state. To store the state, a checkbutton is associated with a variable. When the state of the checkbutton changes, so does that of the variable. An example is:

     checkbutton .on_or_off -text "I like ice cream" -variable ice

which will create a checkbutton with name .on_or_off displaying the text `I like ice cream' and associated with the variable ice. If the checkbutton is checked, ice will have the value 1; if not checked, it will have the value 0. The state of the checkbutton can also be changed by changing the state of the variable. For example, executing

     set ice 0

will set the state of .on_or_off to not checked.

Radiobuttons are buttons that are grouped together to select one value among many. Each button has a value, but only one in the button group is active at any one time. In Tcl/Tk this is achieved by creating a series of radiobutton that share an associated variable. Each button has a value. When a radiobutton is clicked on, the variable has that value and all the other buttons in the group are put into the off state. Similarly, setting the value of the variable is reflected in the state of the button group. An example is:

     radiobutton .first -value one -text one -variable count
     radiobutton .second -value two -text two -variable count
     radiobutton .third -value three -text three -variable count

which creates three radiobuttons that are linked through the variable count. If button .second is active, for example, the other two buttons are in the inactive state and count has the value two. The following code sets the button group to make the button .third active and the rest inactive regardless of the current state:

     set count three

If the value of count does not match any of the values of the radiobuttons, they will all be off. For example executing the script

     set count four

will turn all the radiobuttons off.

An entry widget allows input of a one line string. An example of an entry widget:

     label .l -text "Enter your name"
     entry .e -width 40 -textvariable your_name

would display a label widget named .l showing the string `Enter your name' and an entry widget named .e of width 40 characters. The value of variable your_name will reflect the string in the entry widget: as the entry widget string is updated, so is the value of the variable. Similarly, changing the value of your_name in a Tcl script will change the string displayed in the entry field.

A scale widget is for displaying an adjustable slider. As the slider is moved its value, which is displayed next to the slider, changes. To specify a scale, it must have -from and -to attributes, which is the range of the scale. It can have a -command option, which is set to a script to evaluate when the value of the slider changes.

An example of a scale widget is:

     scale .s -from 0 -to 100

which creates a scale widget with name .s that will slide over a range of integers from 0 to 100.

There are several other options that scales can have. For example it is possible to display tick marks along the length of the scale through the -tickinterval attribute, and it is possible to specify both vertically and horizontally displayed scales through the -orient attribute.

A listbox is a widget that displays a list of single line strings. One or more of the strings may be selected through using the mouse. Initializing and manipulating the contents of a listbox is done through invoking methods on the instance of the listbox. As examples, the insert method is used to insert a string into a listbox, delete to delete one, and get to retrieve a particular entry. Also the currently selected list items can be retrieved through the selection command.

Here is an example of a listbox that is filled with entries of the form entry N:

     listbox .l
     for { set i 0 } { $i<10 } { incr i } {
         .l insert end "entry $i"
     }

A listbox may be given a height and/or width attribute, in which case it is likely that not all of the strings in the list are visible at the same time. There are a number of methods for affecting the display of such a listbox.

The see method causes the listbox display to change so that a particular list element is in view. For example,

     .l see 5

will make sure that the sixth list item is visible. (List elements are counted from element 0.)

A scrollbar widget is intended to be used with any widget that is likely to be able to display only part of its contents at one time. Examples are listboxes, canvases, text widgets, and frames, amongst others.

A scrollbar widget is displayed as a movable slider between two arrows. Clicking on either arrow moves the slider in the direction of the arrow. The slider can be moved by dragging it with the cursor.

The scollbar and the widget it scrolls are connected through Tcl script calls. A scrollable widgets will have a scrollcommand attribute that is set to a Tcl script to call when the widget changes its view. When the view changes the command is called, and the command is usually set to change the state of its associated scrollbar.

Similarly, the scrollbar will have a command attribute that is another script that is called when an action is performed on the scrollbar, like moving the slider or clicking on one of its arrows. That action will be to update the display of the associated scrollable widget (which redraws itself and then invokes its scrollcommand, which causes the scrollbar to be redrawn).

How this is all done is best shown through an example:

     listbox .l -yscrollcommand ".s set" -height 10
     scrollbar .s -command ".l yview"
     for { set i 0 } { $i < 50 } { incr i } {
         .l insert end "entry $i"
     }

creates a listbox named .l and a scrollbar named .s. Fifty strings of the form entry N are inserted into the listbox. The clever part is the way the scrollbar and listbox are linked. The listbox has its -yscrollcommand attribute set to the script ".s set". What happens is that if the view of .l is changed, this script is called with 4 arguments attached: the number of entries in the listbox, the size of the listbox window, the index of the first entry currently visible, and the index of the last entry currently visible. This is exactly enough information for the scrollbar to work out how to redisplay itself. For example, changing the display of the above listbox could result in the following -yscrollcommand script being called:

     .s set 50 10 5 15

which says that the listbox contains 50 elements, it can display 10 at one time, the first element displayed has index 5 and the last one on display has index 15. This call invokes the set method of the scrollbar widget .s, which causes it to redraw itself appropriately.

If, instead, the user interacts with the scrollbar, the scrollbar will invoke its -command script, which in this example is ".l yview". Before invoking the script, the scrollbar widget calculates which element should the first displayed in its associated widget and appends its index to the call. For example, if element with index 20 should be the first to be displayed, the following call will be made:

     .l yview 20

which invokes the yview method of the listbox .l. This causes .l to be updated (which then causes its -yscrollcommand to be called, which updates the scrollbar).

A frame widget does not do anything by itself except reserve an area of the display. Although this does not seem to have much purpose, it is a very important widget. It is a container widget; that is, it is used to group together collections of other widgets into logical groups. For example, a row of buttons may be grouped into a frame, then as the frame is manipulated so will the widgets displayed inside it. A frame widget can also be used to create large areas of color inside another container widget (such as another frame widget or a toplevel widget).

An example of the use of a frame widget as a container:

     canvas .c -background red
     frame .f
     button .b1 -text button1
     button .b2 -text button2
     button .b3 -text button3
     button .b4 -text button4
     button .b5 -text button5
     pack .b1 .b2 .b3 .b4 .b5 -in .f -side left
     pack .c -side top -fill both -expand 1
     pack .f -side bottom

which specifies that there are two main widgets a canvas named .c and a frame named .f. There are also 5 buttons, .b1 through .b5. The buttons are displayed inside the frame. Then the canvas is displayed at the top of the main window and the frame is displayed at the bottom. As the frame is displayed at the bottom, then so will the buttons because they are displayed inside the frame.

(The pack command causes the widgets to be handled for display by the packer geometry manager. The -fill and -expand 1 options to pack for .c tell the display manager that if the window is resized, the canvas is to expand to fill most of the window. You will learn about geometry managers later in the Geometry Managers section.)

A toplevel widget is a new toplevel window. It is a container widget inside which other widgets are displayed. The root toplevel widget has path . — i.e. dot on its own. Subsequent toplevel widgets must have a name that is lower down the path tree just like any other widget.

An example of creating a toplevel widget is:

     toplevel .t

All the widgets displayed inside .t must also have .t as the root of their path. For example, to create a button widget for display inside the .t toplevel the following would work:

     button .t.b -text "Inside 't'"

(Attributes, such as size and title, of toplevel widgets can be changed through the wm command, which we will not cover in this tutorial. The reader is referred to the Tk manual.)

Yet another kind of container is a menu widget. It contains a list of widgets to display inside itself, as a pulldown menu. A simple entry in a menu widget is a command widget, displayed as an option in the menu widget, which if chosen executes a Tcl command. Other types of widgets allowed inside a menu widget are radiobuttons and checkboxes. A special kind of menu item is a separator that is used to group together menu items within a menu. (It should be noted that the widgets inside a menu widget are special to that menu widget and do not have an independent existence, and so do not have their own Tk name.)

A menu widget is built by first creating an instance of a menu widget (the container) and then invoking the add method to make entries into the menu. An example of a menu widget is as follows:

     menu .m
     .m add command -label "Open file" -command "open_file"
     .m add command -label "Open directory" -command "open_directory"
     .m add command -label "Save buffer" -command "save_buffer"
     .m add command -label "Save buffer as..." -command "save_buffer_as"
     .m add separator
     .m add command -label "Make new frame" -command "new_frame"
     .m add command -label "Open new display" -command "new_display"
     .m add command -label "Delete frame" -command "delete_frame"

which creates a menu widget called .m, which contains eight menu items, the first four of which are commands, then comes a separator widget, then the final three command entries. (Some of you will notice that this menu is a small part of the Files menu from the menubar of the Emacs text editor.)

An example of a checkbox and some radiobutton widget entries:

     .m add checkbox -label "Inverse video" -variable inv_vid
     .m add radiobutton -label "black" -variable color
     .m add radiobutton -label "blue" -variable color
     .m add radiobutton -label "red" -variable color

which gives a checkbox displaying `Inverse video', keeping its state in the variable inv_vid, and three radiobuttons linked through the variable color.

Another menu item variant is the cascade variant, which is used to make cascadable menus, i.e. menus that have submenus. An example of a cascade entry is the following:

     .m add cascade -label "I cascade" -menu .m.c

which adds a cascade entry to the menu .m that displays the text `I cascade'. If the `I cascade' option is chosen from the .m menu then the menu .m.c will be displayed.

The cascade option is also used to make menubars at the top of an application window. A menu bar is simply a menu each element of which is a cascade entry, (for example). The menubar menu is attached to the application window through a special configuration option for toplevel widgets, the -menu option. Then a menu is defined for each of the cascade entry in the menubar menu.

There are a large number of other variants to menu widgets: menu items can display bitmaps instead of text; menus can be specified as tear-off menus; accelerator keys can be defined for menu items; and so on.

A menubutton widget displays like a button, but when activated a menu pops up. The menu of the menubutton is defined through the menu command and is attached to the menubutton. An example of a menu button:

     menubutton .mb -menu .mb.m -text "mymenu"
     menu .mb.m
     .mb.m add command -label hello
     .mb.m add command -label goodbye

which crates a menubutton widget named .mb with attached menu .mb.m and displays the text `mymenu'. Menu .mb.m is defined as two command options, one labelled hello and the other labelled goodbye. When the menubutton .mb is clicked on, the menu .mb.m will popup and its options can be chosen.

A canvas widget is a container widget that is used to manage the drawing of complex shapes; for example, squares, circles, ovals, and polygons. (It can also handle bitmaps, text and most of the Tk widgets too.) The shapes may have borders, filled in, be clicked on, moved around, and manipulated.

We will not cover the working of the canvas widget here. It is enough to know that there is a powerful widget in the Tk toolkit that can handle all manner of graphical objects. The interested reader is referred to the Tk manual.

A text widget is another powerful container widget that handles multi-line texts. The textwidget can display texts with varying font styles, sizes, and colors in the same text, and can also handle other Tk widgets embedded in the text.

The text widget is a rich and complicated widget and will not be covered here. The interested reader is referred to the Tk manual.


Send feedback on this subject.