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.