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

I have a multi-column Hlist using Perl Tk. I want to alter the data is some of the columns
Ideally I would like to do something like:
1. Put my cursor over the cell to be changed (a cell being for a specific row and column);
2. Use one of the mouse buttons;
3. Enter the new data
Steps 1 and 2 do seem to highlight the cell. However, I cannot then edit this.
I have looked in Mastering Perl Tk but I cannot see anything that gives this functionality for an Hlist.
So the question is, can this be done with an Hlist and if not what is the best way to approach the problem?
I sort of can see that having a table of entry boxes would give what I want but this may not be simple to implement and manage.
Any comments or answers will be gratefully received.

Replies are listed 'Best First'.
Re: Altering Data in a Tk Hlist
by stefbv (Priest) on Jun 02, 2011 at 06:53 UTC

    In the widgets demo, under Tix Widgets there is "Multicolumn listbox with individual cell styles" example. It has embeded Entry and Button widgets and it might be an option.

    Another option, which I prefer, is Tk::TableMatrix, a good module, useful for editing and presenting data, fast, well documented and with nice examples. (Look for the examples in the module source archive not in the Examples section of the manual).

      Thanks for that. I will have a look at these and see what they can do.
Re: Altering Data in a Tk Hlist
by zentara (Cardinal) on Jun 02, 2011 at 14:13 UTC
    Here is a little example that ought to get you going. The trick is to bind to mouse button 3, or whatever else you can. The original is from an advanced perl programming book, but it didn't use strict. :-)

    You will need to provide a couple of bitmap files for open-folder and close-folder, to run the example. Here they are, save them to files.

    open_folder.xbm

    #define openfolder_width 16 #define openfolder_height 10 static unsigned char openfolder_bits[] = { 0xfc, 0x00, 0x02, 0x07, 0x01, 0x08, 0xc1, 0xff, 0x21, 0x80, 0x11, 0 +x40, 0x09, 0x20, 0x05, 0x10, 0x03, 0x08, 0xff, 0x07};

    folder.xbm

    #define folder_width 16 #define folder_height 10 static unsigned char folder_bits[] = { 0xfc, 0x00, 0x02, 0x07, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0 +x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0xff, 0x07};
    #!/usr/bin/perl #Advanced Perl Programming Chapter 14 -updated use warnings; #use diagnostics; use Tk; require Tk::HList; my $top = MainWindow->new(); my $hlist = $top->Scrolled( 'HList', drawbranch => 1, # yes, draw branches separator => '/', # filename separator indent => 15, # pixels command => \&show_or_hide_dir ); $hlist->pack( -fill => 'both', -expand => 'y' ); $hlist->bind("<Button-3>" => [\&menu_popup, Ev('x'), Ev('y')]); # Read bitmap files and create "image" objects. $open_folder_bitmap = $top->Bitmap( -file => './open_folder.xbm' ); $closed_folder_bitmap = $top->Bitmap( -file => './folder.xbm' ); # Start with the current directory show_or_hide_dir("."); MainLoop(); #--------------------------------------------------------------------- +-- sub menu_popup { my ($wg,$x1,$y1) = @_; print "@_\n"; my ($x, $y) = $top->pointerxy; print "\t$x $y\n"; my $s = $hlist->nearest($y - $hlist->rooty); print "$s\n"; $hlist->selectionClear(); $hlist->selectionSet($s); #pop a dialogbox here and get new text #you can probably popup a editable label to #get the new value my $newtext = 'foobar'; $hlist->itemConfigure($s,0,-text=> $newtext ); # here is some other unsuccesful hacks I tried to make a popup # $wg->eventGenerate('<Button-1>', -x => $x , -y => $y ); # if (my $sel=$wg->info("selection")) { # $top->Popup(-popover => "cursor", # -popanchor => 'nw') # } } sub show_or_hide_dir { # Called when an entry is double-clicked my $path = $_[0]; return if ( !-d $path ); # Not a directory. if ( $hlist->info( 'exists', $path ) ) { # Toggle the directory state. # We know that a directory is open if the next entry is a # a substring of the current path $next_entry = $hlist->info( 'next', $path ); if ( !$next_entry || ( index( $next_entry, "$path/" ) == -1 ) +) { # Nope. open it $hlist->entryconfigure( $path, -image => $open_folder_bitm +ap ); add_dir_contents($path); } else { # Yes. Close it by changing the icon, and deleting its chi +ldren $hlist->entryconfigure( $path, -image => $closed_folder_bi +tmap ); $hlist->delete( 'offsprings', $path ); } } else { die "'$path' is not a directory\n" if ( !-d $path ); $hlist->add( $path, -itemtype => 'imagetext', -image => $open_folder_bitmap, -text => $path ); add_dir_contents($path); } } sub add_dir_contents { my $path = $_[0]; my $oldcursor = $top->cget('cursor'); # Remember current cursor +, and $top->configure( -cursor => 'watch' ); # change cursor to watch $top->update(); my @files = glob "$path/*"; foreach $file (@files) { $file =~ s|//|/|g; ( $text = $file ) =~ s|^.*/||g; if ( -d $file ) { $hlist->add( $file, -itemtype => 'imagetext', -image => $closed_folder_bitmap, -text => $text ); } else { $hlist->add( $file, -itemtype => 'text', -text => $text ); } } $top->configure( -cursor => $oldcursor ); }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
      That is certainly something to look at.
      I can see that using the right mouse button the 'cell' changes to 'foobar' which is 'constant' in the call back.
      Now to get something to appear into which I can add the data I want!
        I'm not going to write simple popup code for you. To do it correctly would take a few hours. There are alot of free examples on the net. I will however, give you a few tips on HList.

        First, when you make a selection, it gets the entire multicolumn row. So when you make your popup dialog for new text, you need to remember, or housekeep, which column you are changing. For example, suppose you had 3 columns, you would need something like

        my $newtext0 = 'foobar0'; #get from a popup dialog or wherever my $newtext1 = 'foobar1'; my $newtext2 = 'foobar2'; $hlist->selectionSet($s); $hlist->itemConfigure($s, 0, -text=> $newtext0 ); #column 0 $hlist->itemConfigure($s, 1, -text=> $newtext1 ); #column 1 $hlist->itemConfigure($s, 2, -text=> $newtext2 ); #column 2
        If you want a free HList program to look at, see ztkdb-sql or ztkdb

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