It's not that hard, but you have to do it manually, and you
need to be familiar with the Hlist methods. But here is a simple demo. I couldn't easily figure out how to make a button-click binding on the HList column header, so I just made a button. Also with more columns (than in this snippet), you will need to sort on (and itemConfigure) more fields.UPDATE: It's easy to make clickable headers, just groups.google search for "Tk HList header bind" for a few examples. I added a second example in the readmore below, to show a double sort.
#!/usr/bin/perl
use strict;
use Tk;
use Tk::HList;
my $mw = MainWindow->new();
#create some sample data
my %data;
foreach (0..100) {
$data{$_}{'name'} = 'name'.$_;
$data{$_}{'id'} = rand(time);
}
#get random list of keys
my @keys = keys %data;
#################
my $h = $mw->Scrolled( 'HList',
-header => 1,
-columns => 2,
-width => 30,
-height => 60,
-takefocus => 1,
-background => 'steelblue',
-foreground =>'snow',
-selectmode => 'single',
-selectforeground => 'pink',
-selectbackground => 'black',
# -browsecmd => \&browseThis,
)->pack(-side => "left", -anchor => "n");
my $nameh = $h->header('create', 0, -text => ' Name ',
-borderwidth => 3,
-headerbackground => 'steelblue',
-relief => 'raised');
my $idh = $h->header('create', 1, -text => ' ID ',
-borderwidth => 3,
-headerbackground => 'lightsteelblue',
-relief => 'raised');
foreach (@keys) {
my $e = $h->addchild(""); #will add at end
$h->itemCreate ($e, 0,
-itemtype => 'text',
-text => $data{$_}{'name'},
);
$h->itemCreate($e, 1,
-itemtype => 'text',
-text => $data{$_}{'id'},
);
}
my $button = $mw->Button(-text => 'exit',
-command => sub{exit})->pack;
my $sortid = $mw->Button(-text => 'Sort by Id',
-command => [\&sort_me,1] )->pack;
MainLoop;
#########################################################
sub sort_me{
my $col = shift;
my @entries = $h->info('children');
my @to_be_sorted =();
foreach my $entry(@entries){
push @to_be_sorted,
[ $h->itemCget($entry,0,'text'),
$h->itemCget($entry,1,'text')
];
}
my @sorted = sort{ $a->[$col] cmp $b->[$col] } @to_be_sorted;
my $entry = 0;
foreach my $aref (@sorted){
# print $aref->[0],' ',$aref->[1],"\n";
$h->itemConfigure( $entry, 0, 'text' => $aref->[0] );
$h->itemConfigure( $entry, 1, 'text' => $aref->[1] );
$entry++;
}
$mw->update;
}
And here is a double sort example:
I'm not really a human, but I play one on earth.
flash japh
| [reply] [d/l] [select] |
Thanks for the code examples. As you suggested, I searched groups.google.com. I found there mention of a very powerful list widget, with built in sorting capabilities. Tk::MListbox. It's pretty impressive. Allows column sorting, hiding columns, etc. It's available as an activestate package. Life is good!
| [reply] |
There was a recent post on comp.lang.perl.tk about MListbox leaking memory, when you make alot of entry changes. I recommended in a response to use HList, because it's methods allow reuse of entries. I actually thought you were the same
person who posted there, because he said the drawback to HList was no built-in sorting. Anyways...watch your memory
with MListbox, if you are doing alot of entry changes.
I'm not really a human, but I play one on earth.
flash japh
| [reply] |
It's true. MListbox leaks memory, but only because the current Listbox in the most recent releases of Tk leaks. If that were fixed, then it would be fine.
I guess I can take a look at updating MListbox to use TextList instead of Listbox like I intended to a year or two ago. I don't believe it has the same memory leak problem. Perhaps I'll create an option that will use one or the other. Unfortunately, I don't think TextList will be as efficient.
The Leak in Listbox is a fairly new thing. I don't recall it being a problem before Tk804.*
Rob
| [reply] |
I guess I can take a look at updating MListbox to use TextList instead of Listbox like I intended
That would be great!
I'm rather new to Perl Tk. Just out of curiousity, is a widget such as Tk::MListbox 'pure Perl'?
| [reply] |
Yes. MListbox is a widget that is built from several Tk core widgets. MListbox consists of no C code itself, and generally relies on its subwidgets to "do the right thing" when it comes to freeing memory that is no longer required.
Each sort operation essentially deletes all data from each Listbox (Column), and then loads each Listbox again with the data once it has been sorted. So, as you can imagine leaks in Listbox are obvious very quickly.
Tk::TextList is a widget that was created several years ago to emulate the functionality provided by Listbox (method calls, look-and-feel, etc), but to give it the power of Text widget tags. In theory, this gives TextList the ability to create and apply styles (tags) at a much greater granularity (per character) than even HList, though, I think the current set of methods support a per-item configuration.
You should be able to plugin TextList every where there is a Listbox call, and it should work, but now that I think about it, there may have been one or two issues with it that I'm not sure if I ever released fixes for. Feel free to experiment with it. I'm going to look at it again as well.
If you have the time to devote to it, I definitely encourage you to experiment with HList. I've also used it for similar purposes in the past, with a reasonable amount of success. Whenver I did, however, I always had this nagging feeling that I was using it to solve problems that it wasn't really created to solve.
| [reply] |