In addition to providing some nice-looking interface elements, Tix offers some useful ways to organize the elements that you create. It does this by providing container widgets, which are widgets designed to contain whatever you want to put into them.
Different container widgets have different policies as to how they arrange the widgets inside them. In this chapter, we'll talk about TixNoteBook, which arranges its subwidgets using a notebook metaphor, TixPanedWindow, which arranges its subwidgets in non-overlapping horizontal or vertical panes, and a family of ``Scrolled Widgets'', which attach scrollbars to their subwidgets.
When your need to put a lot of information into your interface, you may find out that your window has to grow intolerably big in order to hold all the information. Having a window that's 10000 pixels wide and 5000 pixels high doesn't seem to be the perfect solution. Of course, you can ``chop up'' your big window into a set of smaller dialog boxes, but the user will most likely find it impossible to manage 20 different dialog boxes on their desktop.
The TixNoteBook (fig 2-1 ) widget comes into rescue. It allows you to pack a large interface into manageable ``pages'' using a notebook metaphor: it contains multiple pages with anything you want on them, displays one at a time, and attaches a tab to each page so the user can bring it forward with a single click on the tab.
(Figure 2-1) The TixNoteBook Widget
The example program in figure 2-2 creates the
TixNoteBook widget shown in figure 2-1 . In the first
three lines, we create the notebook widget and two pages inside
it. While we create the pages, we also set the labels on the tabs
associated with each page and use the -underline
option to
indicate the keyboard accelerator for each page.
Each time we create a page in the notebook using the add
method, a frame subwidget is created for us automatically. This
frame subwidget has the same name as the page (the first parameter
passed to the add
method). We can use the subwidget
method to find out the pathname of this frame subwidget and pack
everything we want to display on the page into this frame
widget. Lines 4-10 of program 2-2 shows how to create
the widgets inside the ``Hard Disk'' page. Creating the widgets
inside the ``Network'' page will be similar.
tixNoteBook .n .n add hd -label "Hard Disk" -underline 0 .n add net -label "Network" -underline 0set frame [.n subwidget hd] tixControl $frame.access -label "Access Time:" tixControl $frame.write -label "Write Throughput:" tixControl $frame.read -label "Read Througput:" tixControl $frame.capacity -label "Capacity:" pack $frame.access $frame.write $frame.read $frame.capacity
-side top -fill x(Figure 2-2) Using The TixNoteBook Widget
Note that in line 2-3 of program 2-2 , we have indicated
the keyboard accelerators for the two pages using the
-underline
option. The value of this option is the position of the
character to be underlined in the string, where zero represents the
first character. When the user presses <Alt-N>
or
<Meta-N>
the ``Network'' page will be activated; on the other hand,
if he presses <Alt-H>
or <Meta-H>
the ``Hard Disk'' page
will be activated. The TixNoteBook widget will automatically create
the keyboard bindings for these accelerators for us, in a way
similar to what the menu widget does, so there is no need to set the
keyboard bindings ourself.
If your notebook contains many complicated pages, it may take quite a while to create all widgets inside these pages and your program will probably freezes for a few seconds when it pops up the notebook for the first time. To avoid embarrassing moments like this, we can use the ``delayed page creation'' feature of the TixNoteBook widget.
When we create a page using the add
method, we can specify
the optional parameter -createcmd
so that we only need to
create the page when the user wants to see it. This is illustrated
in program 2-3 :
tixNoteBook .n .n add hd -label "Hard Disk" -underline 0 -createcmd CreateHd .n add net -label "Network" -underline 0 -createCmd CreateNetproc CreateHd {frame} { tixControl $frame.access -label "Access Time:" tixControl $frame.write -label "Write Throughput:" tixControl $frame.read -label "Read Througput:" tixControl $frame.capacity -label "Capacity:" pack $frame.access $frame.write $frame.read $frame.capacity
-side top -fill x }proc CreateNet {frame} { ... }
(Figure 2-3) Delayed Page Creation
In line 2 of program 2-3 , we use the -createcmd
option to specify that the procedure CreateHd
should be called
when the ``Hard Disk'' page needs to be created. CreateHd
takes one argument, the frame subwidget of the page. As we can see,
program program 2-3 is not very different than program
2-2 , except now we can issue less commands during the
set-up of the NoteBook widget and the interface can be started up
more quickly.
To change the information in the tabs of the pages, we can use the
pageconfigure
method. For example, the following command:
changes the label from ``Hard Disk'' to ``Fixed Disk''. To delete a page, we can use the.nb pageconfigure hd -label "Fixed Disk"
delete
method.
You should avoid using the pageconfigure
and
delete
. Your users will just feel annoyed if the interface changes
all the time and notebook pages appear and disappear every now and
then.
The TixPanedWindow widget arranges arranges its subwidgets in non-overlapping panes. As we can see in figure 2-4 , the PanedWindow widget puts a resize handle between the panes for the user to manipulate the sizes of the panes interactively. The panes can be arranged either vertically (figure 2-4 ) or horizontally (2-4 ).
Each individual pane may have upper and lower limits of its size. The user changes the sizes of the panes by dragging the resize handle between two panes.
Vertical Panes
Horizontal Panes (Figure 2-4) The TixPane Widget
You can create a TixPanedWindow widget using the tixPanedWindow
command. After that, you can add panes into this widget using the
add
method (see program 2-5 ).
When you use the add
method, there are several optional
parameters which you can use to control the size of each of the
pane. The -min
parameter controls the minimum size of the pane
and the -max
parameter controls its maximum size. These two
parameters controls how much the user can expand or shrink a
pane. If neither is specified, then the pane can be expanded or
shrunk without restrictions.
In addition, the -size parameter specifies the initial size of the pane. If it is not specified, then the initial size of the pane will be its natural size.
In program 2-5 , we set the initial size of pane1
to
100 pixels using the -size parameter. We don't set the -size
parameter for pane2
so it will appear in its natural
size. However, we use the -max
option for pane2
so that
the user can never expand the size of pane2
to more than 300
pixels.
tixPanedWindow .p .p add pane1 -size 100 .p add pane2 -max 300set p1 [.p subwidget pane1] button $p1.b1 -text Button1 button $p1.b2 -text Button2 pack $p1.b1 $p1.b2 -side left -expand yes
set p2 [.p subwidget pane2] button $p2.b -text "Another Button" pack $p2.b -side left -expand yes -fill both
pack .p -expand yes -fill both
(Figure 2-5) Adding Panes into a TixPanedWindow Widget
Each pane we have created using the add
method is essentially
a frame widget. After we have created the panes, we can put widgets
inside them. As shown inside program 2-5 , we can use the
subwidget
method to find out the name of the pane
subwidgets. Then we can just create new widgets as their children
and pack these new widgets inside the panes. The output of program
2-5 is shown in figure 2-6
(Figure 2-6) Output of Program 2-5
Usually, when you create a new pane, it is always added to the
bottom or right of the list of panes. If you want to control the
order in which the panes appear inside the TixPanedWindow widget,
you can use the two optional parameters, -before
and
-after
, for the add
method. For example, the call:
will place the new pane immediately after.p add pane2 -after pane1
pane1
. The call:
will place the new pane immediately in front of.p add pane2 -before pane1
pane1
.
If you want to change the sizes of the existing panes or change
their maximum/minimum size constraints, you can use the
paneconfigure
method. For example, the following code changes the
size of pane2
to 100 pixels and adjusts its minimum size
constraint to no less than 10 pixels:
Notice that after you call the.p paneconfigure pane2 -size 100 -min 10
paneconfigure
method, the
PanedWindow may jitter and that may annoy the user. Therefore, use
this method only when it is necessary.
With plain Tcl/Tk, the widgets do not automatically come with scrollbars. If you want to use scrollbars with the text, canvas or listbox widgets, you will need to create scrollbars separately and attach them to the widgets. This can be a lot of hassle because you would almost always need scrollbars for these widgets. Sometimes you will wonder why you need to write the same boring code again and again just to get the scrollbars to working.
The Tix scrolled widgets are here to make your life easier. With a
single command such as tixScrolledListBox
or
tixScrolledText
, you can create a listbox or text widget that comes
automatically with scrollbars attached.
Another advantage of the Tix scrolled widgets is that you can specify their scrolling policy so that the scrollbars appear only when they are needed. This feature is especially useful if you are displaying a lot of widgets and running out of screen real estate.
You can create a scrolled listbox widget using the
tixScrolledListBox
command. Notice that the widget created by the
tixScrolledListBox
command is not itself a listbox
widget. Rather, it is a frame widget which contains two scrollbar
subwidgets: one is called hsb
(the horizontal scrollbar) and
the other is called vsb
(the vertical scrollbar). Similarly,
the listbox being scrolled is also a subwidget which is
appropriately called listbox
. Therefore, if we need to put
things into the listbox (as we always do!), we can use the
subwidget
method. As shown in program 2-7 , we first
find the pathname of the listbox
subwidget by calling ``
.sl subwidget listbox
''. Then, we insert some items into the
listbox
subwidget.
tixScrolledListBox .sl -scrollbar auto set listbox [.sl subwidget listbox]for {set x 0} {$x < 6} {incr x} { $listbox insert end "This is item $x" }
pack .sl -side left -expand yes -fill both
(Figure 2-7) Scrolled Listbox Widget
Scrollbars not displayed
Scrollbars displayed only when needed (Figure 2-8) Scrolled ListBox with Automatic Scrollbars
Also, as seen in the first line of program 2-7 , we use
the -scrollbar
option to control the scrolling policy of the
TixScrolledListBox widget. Usually, we'll set it to `` auto
'':
the scrollbars are displayed only if they are needed. Other possible
values are `` both
'': the two scrollbars are always displayed;
`` x
'': the horizontal scrollbar is always displayed, while the
vertical scrollbar is always hidden; `` y
'': the opposite of
`` x
''; `` none
'': the two scrollbars are always
hidden. The result of program 2-7 is shown in figure
2-8 .
The TixScrolledText widget is very similar to the
TixScrolledListBox widget, except it scrolls a text subwidget, which
is called text
. One problem with the TixScrolledText widget,
though, is its -scrollbar
option doesn't work in the
auto mode. This is due to a bug in Tk which doesn't report the
width of the text subwidget correctly. Until this bug is fixed
in TK, the auto mode will behave the same way as the both mode
for the TixScrolledText widget.
Another scrolled-widget is TixScrolledWindow. Sometimes you
have a large number of widgets that can't possibly be shown in the
screen all at once and your application doesn't allow you to divide
the widgets into several pages of a TixNoteBook. In this case you
can use TixScrolledWindow. It contains a frame subwidget called
window
. You can just create as many widgets as you need as children
of the window
subwidget. An example is shown in program
2-9 , which uses the TixScrolledWindow widget to
implement a ``cheap'' spreadsheet application. The boxes of the
spreadsheet are just entry widgets and they are packed inside the
window
subwidget. The user will be able to scroll to different
parts of the spreadsheet if it is too large to fit in one screen.
tixScrolledWindow .sw -scrollbar auto set f [.sw subwidget window]for {set x 0} {$x < 10} {incr x} { frame $f.f$x pack $f.f$x -side top -expand yes -fill both for {set y 0} {$y < 10} {incr y} { entry $f.f$x.e$y -width 10 pack $f.f$x.e$y -side left -fill x } }
pack .sw -side left -expand yes -fill both
(Figure 2-9) Cheap Spreadsheet Application with TixScrolledWindow
There are two more scrolled-widgets in the Tix library:
TixScrolledTList scrolls a TixTList widget and
TixScrolledHList scrolls a TixHList widget. The subwidgets that
they scroll are called tlist
and hlist
,
respectively. The use of the TList and HList widgets will be
described in the next chapters.