The New PerlTk.org - Advanced listboxes with Tk::HList
www.mamboteam.com
The New PerlTk.org  
Home
Wednesday, 16 April 2014
 
 
Main Menu
Home
Perl/Tk Widgets
Articles
Scripts
Useful Tips
Links
Contact Us
Search
FAQs
Login Form
Username

Password

Remember me
Forgotten your password?
No account yet? Create one
Advanced listboxes with Tk::HList PDF Print E-mail
Written by Slaven Rezic   
The common listbox widget in Perl/Tk is handy in its usage, but limited in its capabilities. There are many demands in the comp.lang.perl.tk newsgroup for features like multiple columns or different display styles for listbox items.

One answer to these questions is the Tk::HList widget. HList is the hierarchical list widget of Perl/Tk. This widget first appeared in Ioi Kim Lam's Tix widget set for Tcl/Tk and is part of the Perl/Tk core.

Some features of HList are:

  • hierarchical trees (this is not covered by this article)
  • multiple columns
  • headers
  • display items
  • extended binding options
  • associate data with list items

Basic usage

The script basic.pl shows a short example for the usage of a HList widget. Note that you have to insert the line
    use Tk::HList;
to use this widget. The creation of a HList does not differ from other Perl/Tk widgets:
    $hl = $top->HList->pack;
HList entries are inserted with the add method. You have to specify an entry path for each HList entry. Entry paths are just unique names for each list item (the term "path" is used because HList was designed to display trees like directory structures). If you don't care, you can simply use a counter for the entry path, like I did in the example. The sorting of the entries is by default determined by the lexically order of the entry paths. You can also use the options -at, -before or after to set the position in another way. Here's an example:

 Add an entry with the string "Bla" and the entry path "bla" into the HList:

    $hl->add("bla", -text => "Bla");
Add an entry with the string "Foo" before "bla":
    $hl->add("foo", -before => "bla", -text => "Foo");
Add an entry with the string "abc" after "bla":
    $hl->add("abc", -after => "bla", -text => "abc");
Add an entry at the the second position (indexes start at zero):
    $hl->add("def", -at => 1, -text => "def");

Multiple columns

With the standard Listbox widget, one could only create multiple columns by using a fixed font with fixed record lengths for each listbox item.

With HList, you can supply the -columns option at the creation of a HList to create a multi-column listbox. See the script multicol.pl for an example.

In a multi-column HList, the add method will set the first column of an entry. The other columns are created with the itemCreate method:

$hl->itemCreate($entry, $column, -text => $text);
The column indexing starts at zero. It's also possible to use the itemCreate method to set the first column instead of the add method (which would be a more orthogonal approach).

List headers

When using multiple columns, it would be nice to have headers for these columns. It is possible to use the first row as the header, but if you have a scrolled HList, this row could go out of sight. So it's better to configure HList to use real headers. At creation time, add this line to enable headers:
-header => 1
The header items are created with the headerCreate method. The syntax is similar to the itemCreate method, except that there is no $entry argument. Here's an example script (header.pl). Image

Various styles

You are not limited to only display text in a HList. The option -itemtype controls, whether images and/or text should be displayed. The allowed values are text (default), image, imagetext, to display text and an image to the left, and window, to display arbitrary widgets. For an example using images and texts, look at the script imagetext.pl.

Image

Moreover, you can assign individual styles to each HList item. This is done using the Tix concept Display Items. There is a manpage Tk::DItem describing this concept and providing examples.

For using display items, first include the ItemStyle module:

    use Tk::ItemStyle;
After that you can create new styles. Styles can be used by more than one item, so create equal styles only once.
    $style = $hl->ItemStyle("text",
                            -foreground => "red",
                            -background => "green",
                            -font => "Times 24");
The first argument (here: "text") specifies the validity of the style definition, which have to match the itemstyle defintion. To use this style, supply the -style option to an add or itemCreate method:
    $hl->add("foo", -style => $style, -text => "Text");
Or to re-configure an existing HList item:
    $l->itemConfigure("foo", 0, -style => $style);
Some further examples can be found in ditem.pl.

Other conveniences

With the standard listbox widget, mouse and key bindings have to be defined with the bind method. HList has two parameters -browsecmd and -command, which simplify the addition of callbacks. Both options accept a standard Perl/Tk callback (e.g. an anonymous subroutine) as its parameters. The -command callback will be called if the user double-clicks on an entry. The -browsecmd callback will be called if the user "browses" through the list, that is, either single clicks on a list entry or moves the anchor with the arrow keys. The complete binding description can be found at the Tk::HList manpage.

With the -data option, it is possible to bind data to list entries. The data argument can be any perl scalar, so array and hash references are allowed, too. Data can be retrieved with the info("data") method:

    $hl = $top->HList->pack;
    # Set entry and data
    $hl->add("abc",
             -text => "An entry",
             -data => ["associated", "data"],
            );
    # Retrieve data
    use Data::Dumper;
    print Data::Dumper->Dump([$hl->info("data", "abc")], ['data']), "\n";

Alternatives

There are some other alternatives to get similar functionality of Hlist's. If you don't mind the appearance, for multiple columns one can use the fixed-font approach described above. Another method is to use a Text widget with the -tabs option. This option sets tabular stops which can be used to define multiple columns. The example below will set two tab stops at 2cm and 4cm:
    use Tk;
    $top = new MainWindow;
    $txt = $top->Text(-tabs => [qw/2c 4c/])->pack;
    $txt->insert("end",
                 "X\tY\tX*Y\n" .
                 "1\t1\t1\n" .
                 "2\t2\t4\n" .
                 "3\t3\t9\n" .
                 "4\t4\t16\n");
    MainLoop;
If you are familiar wih Text widgets, this could be the way to go. The common Text tag mechanisms are available for representing different styles.

The Tk::TiedListbox by Andrew Allen (at CPAN in the Tk-Contrib distribution) provides a way to tie the scrolling of two or more listboxes. That way multi-column listboxes can be emulated by placing several TiedListboxes side by side.

There is another module which appeared in the perl/Tk mailinglist by Greg London called TextList. This module emulates the Tk::Listbox behaviour with a Text widget. That is, all method calls are the same as in Tk::Listbox, but the user can additionaly use the tag mechanism of Text widgets.

Damion K. Wilson has contributed another multi-column listbox in his Tk-DKW package, called Tk::Columns. Additional features are headers and resizable column width (with the technique used for instance in the Netscape mail program). By clicking a header, the listbox gets sorted by this column. The API is simpler than that of HList: for inserting a row with three columns one would simply write:

    $Columns->insert ('end', 'List', 'Row', 'Contents');
Here's a screenshot of a Tk::Columns demonstration script:  Image

That's all! As you see, there is always a great variety to achieve a goal with Perl/Tk.

Comments
finding data from nth line in hlist
Written by mem on 2006-08-08 00:33:10
how do u find out what list entry was clicked on. 
 
its all very well if you have only one line called abc.
finding data from nth line in hlist
Written by carno on 2006-09-04 13:16:25
The path to the line is passed as the first argument to the callback. Here's a modified version of the example script on CPAN - the -command option used on creation and sub hl_browse are what you'll be interested in: 
 
use strict; 
use Tk; 
use Tk::HList; 
use Tk::ItemStyle; 
 
my $mw = MainWindow->new(); 
 
my $hlist = $mw->HList(-columns=>2, -header => 1, -command => \&hl_command, -browsecmd => \&hl_browse, -selectmode => 'single')->pack(-fill => 'x'); 
$hlist->header('create', 0, -itemtype => 'text', -text => "Name") ; 
$hlist->header('create', 1, -itemtype => 'text', -text => "Amount") ; 
 
 
my $red = $hlist->ItemStyle('text', -foreground => '#800000'); 
my $blue = $hlist->ItemStyle('text', -foreground => '#000080', -anchor=>'e'); 
 
foreach ([Joe => '$10,000'], [Peter => '$20,000'], [Raj => '$90,000'], [Zinh => '$0']) { 
my $e = $hlist->addchild(""); 
$hlist->itemCreate($e, 0, -itemtype=>'text', -text=>$_->[0], -style=>$red ); 
$hlist->itemCreate($e, 1, -itemtype=>'text', -text=>$_->[1], -style=>$blue); 

 
my $sel_name = "" ; 
my $sel_amt = "" ; 
my $e1 = $mw->Entry(-textvariable => \$sel_name)->pack(-side => 'bottom', -fill => 'x') ; 
my $e2 = $mw->Entry(-textvariable => \$sel_amt )->pack(-side => 'bottom', -fill => 'x') ; 
 
Tk::MainLoop; 
 
sub hl_browse 

# this one gets called on mouse button 1 release 
my $path = shift ; 
$sel_name = $hlist->itemCget($path, 0, "-text") ; 
$sel_amt = $hlist->itemCget($path, 1, "-text") ; 

finding data from nth line in hlist
Written by carno on 2006-09-04 13:34:23
The path to the line is passed as the first argument to the callback. Here's a modified version of the example script on CPAN - the -command option used on creation and sub hl_browse are what you'll be interested in: 
 
use strict; 
use Tk; 
use Tk::HList; 
use Tk::ItemStyle; 
 
my $mw = MainWindow->new(); 
 
my $hlist = $mw->HList(-columns=>2, -header => 1, -command => \&hl_command, -browsecmd => \&hl_browse, -selectmode => 'single')->pack(-fill => 'x'); 
$hlist->header('create', 0, -itemtype => 'text', -text => "Name") ; 
$hlist->header('create', 1, -itemtype => 'text', -text => "Amount") ; 
 
 
my $red = $hlist->ItemStyle('text', -foreground => '#800000'); 
my $blue = $hlist->ItemStyle('text', -foreground => '#000080', -anchor=>'e'); 
 
foreach ([Joe => '$10,000'], [Peter => '$20,000'], [Raj => '$90,000'], [Zinh => '$0']) { 
my $e = $hlist->addchild(""); 
$hlist->itemCreate($e, 0, -itemtype=>'text', -text=>$_->[0], -style=>$red ); 
$hlist->itemCreate($e, 1, -itemtype=>'text', -text=>$_->[1], -style=>$blue); 

 
my $sel_name = "" ; 
my $sel_amt = "" ; 
my $e1 = $mw->Entry(-textvariable => \$sel_name)->pack(-side => 'bottom', -fill => 'x') ; 
my $e2 = $mw->Entry(-textvariable => \$sel_amt )->pack(-side => 'bottom', -fill => 'x') ; 
 
Tk::MainLoop; 
 
sub hl_browse 

# this one gets called on mouse button 1 release 
my $path = shift ; 
$sel_name = $hlist->itemCget($path, 0, "-text") ; 
$sel_amt = $hlist->itemCget($path, 1, "-text") ; 

Only registered users can write comments.
Please login or register.

Powered by AkoComment 2.0!

< Prev   Next >
 
Top! Top!