Book HomeMastering Perl/TkSearch this book

23.8. The NoteBook Widget

Displaying a lot of information in a small space is often the biggest challenge given to GUI programmers. The NoteBook widget is designed to help do just this. It allows us to have many pages of text, but lets only one be shown at a time. Each page in the NoteBook has a tab associated with it. The tab can display text or an image. Let's look at a simple example:

use Tk;
$mw = MainWindow->new( );
# Create the notebook and fill the whole window
$nb = $mw->NoteBook( )->pack(-expand => 1, -fill => 'both');
# Page 1 on the notebook, with button on that page
$p1 = $nb->add('page1', -label => 'Page 1');
$p1->Button(-text => 'Click me!')->pack( );
# Empty page 2
$nb->add('page2', -label => 'Page 2');
MainLoop;

It creates a window with a NoteBook widget, shown in Figure 23-15. The notebook has two pages, named Page 1 and Page 2, respectively. Page 1 has a button on it, so the size of the NoteBook is determined by Page 1 (because it is the largest).

Figure 23-15

Figure 23-15. Simple NoteBook example

23.8.1. Creating Pages

When you create a page in a NoteBook, you assign it a name using the add method. From then on, when calling NoteBook methods, you refer to that page by that name. In our example, we used page1 and page2 as the internal page names. The displayed label can either be the same or something completely different. It is important that you use different internal names for every single page in the NoteBook, or you'll get an error. Here are some examples using the add method:

$p = $notebook->add('internalname', -label => 'Displayed Name');
$p2 = $notebook->add('internalname2', -bitmap => 'bitmapname');

The first argument passed to add is the internal storage name of the page. There are several options that will determine how the tab information is displayed:

-anchor => anchordir
Anchors the text or image within the notebook tab. Values are: 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw', or 'center'.

-bitmap => bitmap
A bitmap to use on the tab, instead of a label.

-image => imageptr
An image to display instead of a label. Overrides both -bitmap and -label.

-label => string
A string with which to label the tab.

-justify => 'left' | 'right' | 'center'
Direction for the text to justify within the tab.

-createcmd => callback
A callback that is invoked the first time the page is shown. This is useful if you have a lot of processing that can be delayed.

-raisecmd => callback
Invoked every time the page is shown to the user.

-state => 'normal' | 'disabled'
The state of the page.

-underline => index
Which character to underline in the tab. Starts at 0.

-wraplength => length
The maximum length of a line of text on the tab.

Once the page is created, you still need to put something on it. Use the reference returned by the add method and create widgets using that reference as the parent widget.

There are three ways to put something on a page:

To delete a page, use the delete method and pass it the internal name of the page:

$notebook->delete("page1");

There are two methods used to get and set information associated with a page: pagecget and pageconfigure. Both methods will work only with the same options that can be used with the add method.

To get the value of an individual option, use pagecget:

$state = $notebook->pagecget("pagename", -state);

To change the value of one or more options, use pageconfigure:

$notebook->pageconfigure('pagename', -label => 'new label');
$notebook->pageconfigure('pagename', -label => 'new label', -underline => 3);

You can cause a page to be displayed (or raised) by using the raise method:

$notebook->raise("page4");
## OR check to see if that page is already showing:
$page = $notebook->raised( );
if ($page ne "page4")
    $notebook->raise("page4");

23.8.2. WordCount Example Using a NoteBook

A NoteBook allows us to display data in an organized fashion. In this example, we are going to parse through some files (passed in as command-line parameters) and index out all the words contained within the files. The resulting window is shown in Figure 23-16; the code follows.

Figure 23-16

Figure 23-16. WordCount results displayed using a NoteBook

Half of the following code preps the list of words to display and the other half does the work of displaying it. To sort the words, we use a hash based on the first character in each word.

use Tk;
require Tk::NoteBook;

$mw = MainWindow->new( );
# Show the user the names of files we are parsing
# This might end up too long to see it all
$mw->title('Word Count:' . join (',', @ARGV));

# Use a courier font to display the tab text
$nb = $mw->NoteBook(-font => 'Courier 10 bold')->pack;

my %textWidgets;

%seen = ( );
while (<>) {
  while ( /(\w['\w-]*)/g) {
    $seen{lc $1}++;
  }
}

# go through the index in order and create the tabs and text widgets.
foreach my $word (sort (keys %seen)) {
  if ($word =~ /^(.)/) {
    $letter = $1;
    $t = $textWidgets{$letter};
    
    # Create the text widget if it doesn't already exist
    if (! defined $t) {
      my $p = $nb->add($letter, -label => $letter);
      $t = $p->Scrolled("Text")->pack(-expand => 1, -fill => 'both');
      $textWidgets{$letter} = $t;
    }
    $t->insert("end", $seen{$word} . "        " . $word . "\n");
  }
}

MainLoop;

23.8.3. NoteBook Limitations

You can't have the tabs for a NoteBook automatically wrap around and make more than one line of tabs. Consequently, you might make so many tabs that your window will be too big to be displayed properly. In that case, you might consider having a page contain another NoteBook widget, which will essentially give you two rows of tabs.

In order to disable a tab page, the recommended solution is to use an InputO widget, which covers everything on that tab page. However, InputO isn't supported on Win32 systems.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.