skywalker has asked for the wisdom of the Perl Monks concerning the following question:

Hi am writing a Tk routine routine with MListbox, using this to enable users to sort on individual columns is just what I am after, using the -sortable option is great however I need to do some other processing once the sort has taken place. I know I can use a call back using

-comparecmd => \&some_sub

using this seems to only enable sorting on the first column.

ive also tried using sortable and then binding to the header but this seems to disable the sort as well

any pointers as to where this is going wrong would be greatly appreated.

thanks Skywalker

code:
#!/usr/local/bin/perl use Tk; use Tk::MListbox; use strict; my $mw = new MainWindow(-title => 'Spooler Queue'); # Mainwindow: sizex/y, positionx/y $mw->geometry("1200x675+0+175"); my $start = 1; my @data = <DATA>; my %spool_list = (); my $total_spools = 0; my @user = (); my @customers = (); my $reg_exp = ""; my $delimiter = "\t"; my %hash_store = (); my $ctr = 0; my $status_msg = 'Running'; my $timer = 0; my $thr = undef; my $thread_running = 1; #header setup my @goods_issues_headers = ( "URN", "USER", "PDC", "SPOOL TO", "FILE"); my $scalar_header = scalar @goods_issues_headers; my $counter = 0; my $user = ""; @user = (); for my $line (@data){ chomp $line; if($line =~ /^USER/){ $user = $line; next; } if($line =~/^FILE/){ $total_spools = sprintf("%05d",$total_spools); $spool_list{$total_spools}{USER} = $user; $spool_list{$total_spools}{PDC} = $user[0]; $spool_list{$total_spools}{PS} = $user[1]; $spool_list{$total_spools}{SPOOL} = $user[2]; $spool_list{$total_spools}{MAIL} = $user[3]; $spool_list{$total_spools}{LINE} = $line; $total_spools++; }else{ if($line !~ /END PDC/){ push (@user,$line); next; }else{ $total_spools = sprintf("%05d",$total_spools); @user = (); } } } close (DATA); #populate list box foreach my $spool (sort keys %spool_list){ my @list = (); my $temp = $spool_list{$spool}{USER}; $temp =~ s/^USER\-\>//; push (@list,$spool,$temp); my @temp_store = split (/\\|\//,$spool_list{$spool}{PDC}); my $pdc = pop (@temp_store); $pdc =~ s/_PReS_Spooler.pds//; push (@list,$pdc); push (@list,$spool_list{$spool}{SPOOL}); @temp_store = split (/\\|\//,$spool_list{$spool}{LINE}); push (@list,pop (@temp_store)); push (@customers,[@list]); } #setup the main display grid my $grid = $mw->Scrolled('MListbox', -sortable => 1, -scrollbars => 'osoe', -background => 'white', -foreground => 'black', -textwidth => 25, -highlightthickness => 2, -width => 1, -selectmode => 'single', -bd=>2, -columns=>[ [qw/-text URN -textwidth 10/, -comparecmd => \&test], [qw/-text USER -textwidth 20/, -comparecmd => \&test], [qw/-text PDC -textwidth 30/, -comparecmd => \&test], [qw/-text SPOOL -textwidth 30/, -comparecmd => \&test], [qw/-text FILE -textwidth 120/, -comparecmd => \&test], ], -relief=>'sunken')->pack(-side => 'left', -fill => 'both', -expand => 1 ); #keep querry grid upto date &populate_grid($grid,scalar @goods_issues_headers-1,\@customers); MainLoop(); #manage the goods issues display widget sub populate_grid{ my ($widget,$headersize,$customers) = @_; my @customers_array = @{$customers}; my @rowline = (); foreach my $row_number ( 0 .. $#customers_array ) { push (@rowline,$customers_array[$row_number]->[0]); foreach my $x ( 1 .. $headersize ) { push (@rowline,$customers_array[$row_number]->[$x]); } $grid->insert('end',[@rowline]); @rowline= (); } } #sort selected column and also do some other processing sub test{ #do some extra processing when the header is clicked if($start){ print "Sorted\n"; } return ($_[0] <=> $_[1]); } __DATA__ USER->John PDC->{1}J:/j01111.pds COMPILER->PS SPOOL->J:/Postscript to PDF/in DELETE->MAIL DATE:20/12/2008 FILE->J:/J02226_GASTROANB_LOOKED_UP_CU_GASTROANB-STL_PROOFS.CSV FILE->J:/J02226_GASTROCDMMP_LOOKED_UP_CU_GASTROCDMMP-STL_PROOFS.CSV END PDC USER->Paul PDC->{1}J:/j02222.pds COMPILER->PS SPOOL->J:/Postscript to PDF/out DELETE->MAIL DATE:20/12/2008 FILE->J:/J02226_GASTROANB_LOOKED_UP_CU_GASTROANB-STL_PROOFS.CSV FILE->J:/J02226_GASTROCDMMP_LOOKED_UP_CU_GASTROCDMMP-STL_PROOFS.CSV END PDC USER->Singo PDC->{1}J:/J02226 Dendrtie DJ9485 December UTD Mailing/Layout/j03333.p +ds COMPILER->PS SPOOL->C:/temp DELETE->MAIL DATE:20/12/2008 FILE->J:/J02226_GASTROANB_LOOKED_UP_CU_GASTROANB-STL_PROOFS.CSV FILE->J:/J02226_GASTROCDMMP_LOOKED_UP_CU_GASTROCDMMP-STL_PROOFS.CSV END PDC

Replies are listed 'Best First'.
Re: Mlistbox Sort
by zentara (Cardinal) on Feb 17, 2009 at 18:49 UTC
    Update: Not to leave you without a pointer. What you want to do is figure out how to itemconfigure the list column headers, so that only the header clicked is configured as 'sortable', and returned to unsortaable as soon as the sort finishes. IIIYC.

    Your code/problem seems like work :-) A bit of advice, relying on MListbox's built in sort with header click, will not offer you the most flexibility and control. Always store data in arrays, do sorting whatever way you want on the array, then just use the MListbox ( or whatever widget) to display the array.

    Here is the only example I have to show sorting all rows, based on the values in the other rows. Other than that.... hire me and I'll make it work :-)

    #!/usr/bin/perl use warnings; use strict; use Tk; use Tk::MListbox; ### Build Main Window # my $mainWindow = MainWindow->new; $mainWindow->geometry("800x600"); my $frame = $mainWindow->Frame(-bd => 2, -relief => 'raised')->pack(- +expand => 1, -fill => 'both'); my $scrolledMListbox = $frame->Scrolled( qw/ MListbox -selectmode browse -scrollbars oe / )->pack(-expand => 1, -fill => 'both'); $scrolledMListbox->columnInsert('end', -text=>'Date', -sortable=>1, +-width => 10); $scrolledMListbox->columnInsert('end', -text=>'Time', -sortable=>1, +-width => 10); $scrolledMListbox->columnInsert('end', -text=>'Property', -sortable= +>1, -width => 10); $scrolledMListbox->columnInsert('end', -text=>'Name', -sortable=>1, +-width => 10); $scrolledMListbox->columnInsert('end', -text=>'Address', -sortable=> +1, -width => 10); $scrolledMListbox->columnInsert('end', -text=>'Phone', -sortable=>1, + -width => 10); $scrolledMListbox->bindRows('<ButtonRelease-1>', sub { my ($w, $infoHR) = @_; print "@_\n"; print "You selected row: " . $infoHR->{-row} . " in column: " . $infoHR->{-column} . "\n"; print $scrolledMListbox->getRow( $scrolledMListbox->curselection +()->[0] ),"\n"; } ); for (my $count = 100; $count >= 1; $count--){ $scrolledMListbox->insert('end', [[int rand 20], [int rand 20], [ +int rand 20], [int rand 20], [int rand 20], [int rand 20]]); } MainLoop;

    I'm not really a human, but I play one on earth My Petition to the Great Cosmic Conciousness

      Thanks for that

      ive setup the bind to the header and then sorted the array as is, this enables me to also determine the type of sort to do on each column.

      code

      #bind to the header column, to enable sorting and also so we can distr +oy the thread $grid->bindColumns('<Button-1>' => sub { my ($w, $infoHR) = @_; my $column = $infoHR->{-column}; #change the queue status to HOLD while any user interaction is + occuring &button_setup('HOLD','Red'); #kill current processing thread print "Thread destroyed\n"; $thr->cancel(); my @entirelist = $grid->get(0,"end"); $grid->delete(0,"end"); #sort selected column if($column =~/0|2/){ @entirelist = sort {$a->[$column] <=> $b->[$column]} @enti +relist; }else{ @entirelist = sort {lc$a->[$column] cmp lc$b->[$column]} @ +entirelist; }; &populate_grid($grid,scalar @goods_issues_headers-1,\@entireli +st); });
      all I need to do now is add in reverse and its away and running.

      thanks skywalker