in reply to Sorted lists in Tk

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:
#!/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); $data{$_}{'priority'} = int rand 50; } #get random list of keys my @keys = keys %data; ################# my $h = $mw->Scrolled( 'HList', -header => 1, -columns => 3, -width => 40, -height => 40, -takefocus => 1, -background => 'steelblue', -foreground =>'snow', -selectmode => 'single', -selectforeground => 'pink', -selectbackground => 'black', # -browsecmd => \&browseThis, )->pack(-side => "left", -anchor => "n"); $h->header('create', 0, -text => ' Name ', -borderwidth => 3, -headerbackground => 'steelblue', -relief => 'raised'); $h->header('create', 1, -text => ' ID ', -borderwidth => 3, -headerbackground => 'lightsteelblue', -relief => 'raised'); $h->header('create', 2, -text => ' Priority ', -borderwidth => 3, -headerbackground => 'lightgreen', -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'}, ); $h->itemCreate($e, 2, -itemtype => 'text', -text => $data{$_}{'priority'}, ); } my $button = $mw->Button(-text => 'exit', -command => sub{exit})->pack; my $sortid = $mw->Button(-text => 'Sort by Id', -command => [\&sort_me,1] )->pack; my $sortpriority = $mw->Button(-text => 'Sort by Priority', -command => [\&sort_me,2] )->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'), $h->itemCget($entry,2,'text'), ]; } my @sorted = sort{ $a->[$col] cmp $b->[$col] || #primary sort ascii + $a->[1] <=> $b->[1] #secondary sort num +eric } @to_be_sorted; my $entry = 0; foreach my $aref (@sorted){ # print $aref->[0],' ',$aref->[1],' ',$aref->[1],"\n"; $h->itemConfigure( $entry, 0, 'text' => $aref->[0] ); $h->itemConfigure( $entry, 1, 'text' => $aref->[1] ); $h->itemConfigure( $entry, 2, 'text' => $aref->[2] ); $entry++; } $mw->update; }

I'm not really a human, but I play one on earth. flash japh

Replies are listed 'Best First'.
Re^2: Sorted lists in Tk
by mhearse (Chaplain) on May 04, 2005 at 17:25 UTC
    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!
      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
        There was a recent post on comp.lang.perl.tk about MListbox leaking memory

        I see that. I tried rewriting the list using Tk::MListbox in my app. Whenever the sort functionality is used, it leaks about 20KB of memory. Just so I understand, with Tk::Hlist, you can't bind a sort function to the column, right? I don't really want to clutter things up with buttons, unless I have to. Is there any way to work around this memory problem? Your post had mentioned -reconfigure...