Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Re: perl/Tk and expandable widgets

by zentara (Archbishop)
on Jun 08, 2005 at 11:19 UTC ( [id://464633]=note: print w/replies, xml ) Need Help??


in reply to perl/Tk and expandable widgets

I would say that you are trying to use the wrong widgets to do what you want.

First, you will have problems getting the columns to line up between a label and a ROText widget. Their is no uniform connection between the 2, especially if you allow font changes

Second, sorting on a column will be tricky, but can be done. You will have to read all your ROText, split on tabs, sort, then rewrite.....all hoping that the columns will still line up with the headers.

You might be able to work out some sort of Table with TableMatrix, because it sounds like you are looking for a way for your data to display like an html table would. That is an auto-adjust of column width to the largest entry.

A variant of this question was asked a few weeks ago, about sorting lists by clicking on the headers. Sorry that I can't find the node, but had to do with MListbox leaking some memory.

Anyways, you should look at one of the listbox modules. MListbox is designed for column sorting. I recommended the HList, which is harder to use, but can be made to run without leaking memory on sorting. MListbox probably can too, but I don't have a good MListbox example handy. So here is an HList 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; } __END__
I forgot to include the code for doing a "Clickable Header" in an HList
#!/usr/bin/perl use warnings; use strict; use Tk; use Tk::HList; my $mw = new MainWindow; my $'HList',->Scrolled( -scrollbars => 'os', -background => 'white', -columns => 4, -header => 1, -width => 40, -height => 5 )->pack; my $bgcolor = "bisque"; foreach my $column ( 0 .. 3 ) { ## Create the Clickable Header my $b = $hl->Button( -background => $bgcolor, -anchor => 'center', -text => "Header$column", -command => sub { print "You pressed Header $column\n"; } ); $hl->headerCreate( $column, -itemtype => 'window', -borderwidth => -2, -headerbackground => $bgcolor, -widget => $b ); } MainLoop;

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

Replies are listed 'Best First'.
Re^2: perl/Tk and expandable widgets
by hexcoder (Curate) on Jan 18, 2013 at 10:00 UTC
    Thanks for the demo code!

    I like to add a bugfix in the second code snippet in line 8:

    my $'HList',->Scrolled(

    should be

    my $hl = $mw->Scrolled('HList',

Re^2: perl/Tk and expandable widgets
by Elijah (Hermit) on Jun 09, 2005 at 18:43 UTC
    Good suggestion but this still does not solve the issue of fixed size buttons/windows for each category. I was more interested in a way to make these fields expandable by clicking and dragging. I have read through the docs on HList and it does not seem possible to do. Am I missing something or is this just one of those things that perl is not going to be able to do?

    Edited:
    It seems that Tk::Columns is what I would need to accomplish this.
      I would say you are "pushing the edge" of Tk's abilities. My first inclination would be to reconfigure the header buttons after you know how wide they should be. You could scan the column for the widest entry, then reconfigure the header button text to be padded to that width. Maybe you would have to packForget and repack too. Sounds like you need to experiment a bit. :-) You can reconfigure the headers of an HList to be different text, but like I said earlier, you will run into the problems of the -width specification being different amoung different widgets. Maybe if you confine everything to a certain font?

      I'm not really a human, but I play one on earth. flash japh
        This thread is old, but...
        I have used a modified HList I found on CPAN called Tk::HListplus that worked quite well for this problem.,
        It uses (as an example):
        $widget->header('create', 0, -itemtype => 'resizebutton', -text => 'Pa +th');
        It allows you to double click on a header to make the column about 1 character wide (so you can grow it again) and also permits the mouse to grab the right side of the header box to adjust the column width.
        I also don't see a problem with initally having the column the correct size for the contents. I use:
        $widget->columnwidth($column_number,'');
        to make it automatic.
        I would recommend using:
        $widget = $host_box->Scrolled(qw/HListplus -scrollbars osoe/);
        so that you have enough room regardless of the host_box size.
        (1st post)
      It seems that Tk::Columns is what I would need to accomplish this.

      Note that Tk::Columns, although a decent widget, suffers from the same memory leak problems as Tk::MListbox, because the problem does't truly originate from either one, but from Tk::Listbox that leaks.

      Both of these widgets tend to do sorts faster than what HList will support, because implementing it in HList involves a call for every cell in the Tabular display, where both Columns and MListbox require two for each column: one to delete all entries, and the second to reinsert the sorted elements. For large numbers of rows, this difference can be significant.

      Of course... that extra boost of speed is small comfort when you are blissfully sorting large amounts of data and leaking memory like crazy...

      Rob
Re^2: perl/Tk and expandable widgets
by rcseege (Pilgrim) on Nov 04, 2005 at 03:44 UTC

    I agree, Zentara with pretty much everything you said. I didn't realize, until one of your recent posts that the memory leak with Listbox didn't occur when you pass an array reference to the Listbox and manipulating its contents through that. I'm going to take a look at setting up MListbox to use that. Unfortunately, if I do, then it won't be backwards compatible, since it will rely on an API change in 804*.

    It's barely worth mentioning, but your solution using HList will still leak if you end up getting smaller result sets, and you are forced to delete entries. The point is, the leak will be significantly less than if you were deleting and recreating everything each update. Reconfiguring is also more efficient for updates than deleting/recreating everything.

    Rob

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://464633]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (6)
As of 2024-04-20 02:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found