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

I would like to do following by using -tk?

The program should create a frame which is divided in two parts, left subframe and right subframe. When the program is run, filenames of files in the same folder as the program, appear in the left subframe. By clicking on each of the filenames, the content of the file is displayed in the righ frame.
(The content of the files are numbers. The numbers from the files clicked are processed and figures are drawn in the right frame according to the numbers.)
Could you give me some general directions how to do this in the best way?

(I do not ask for any code)

Thank you for any help

2006-09-22 Retitled by planetscape, as per Monastery guidelines: one-word (or module-only) titles hinder site navigation

( keep:0 edit:19 reap:0 )

Original title: 'tk-question'

Replies are listed 'Best First'.
Re: TK question: navigating frames
by liverpole (Monsignor) on Sep 21, 2006 at 14:12 UTC
    Hi tamaguchi,

    Once you have the left and right frames setup, figure out what kind of widget you want to display files in.  Easiest is probably a Text widget, into which you can write the filenames, one per line, with a tag configured on each one.  (You can use the file's name for the tag to guarantee each file has a unique tag name.)  You simply bind a subroutine to the tag for each filename, such that when you click on it, that subroutine gets invoked.

    Although you "dont' ask for code", I'll provide you a very simple example of configuring tags for inserting text into a Text widget, as I hope that will help you get started:

    use strict; use warnings; use Tk; my $mw = new MainWindow; my $tw = $mw->Text()->pack(-expand => 1, -fill => 'both'); foreach my $item (qw( item1 item2 item3 )) { my $tagname = $item; $tw->tagBind($tagname, "<Button-1>", sub { clicked_item($item) }); $tw->insert('end', $item, $tagname); $tw->insert('end', "\n"); } MainLoop; sub clicked_item { my ($item) = @_; print "You clicked on item $item!\n"; }

    You may also want to change the cursor so as to get a visual clue when the mouse is over text that can be selected.  This can be a little tricky, so I'll explain it here.

    What you need is a subroutine to change the cursor whenever the mouse is hovering over a given tag, and another to change the cursor back.  Hovering over a tag is an event called "<Any-Enter>", and moving away is called "<Any-Leave>".  You can create these anonymous subroutines (called $p_enter and $p_leave below), and then bind them to the tag the same way as you bound the named subroutine clicked_item.

    Here's the full example:

    use strict; use warnings; use Tk; my $mw = new MainWindow; my $tw = $mw->Text()->pack(-expand => 1, -fill => 'both'); my $p_enter = sub { $_[0]->configure(-cursor => 'hand2') }; my $p_leave = sub { $_[0]->configure(-cursor => 'xterm') }; foreach my $item (qw( item1 item2 item3 )) { my $tagname = $item; $tw->tagBind($tagname, "<Button-1>", sub { clicked_item($item) }); $tw->tagBind($tagname, "<Any-Enter>", $p_enter); $tw->tagBind($tagname, "<Any-Leave>", $p_leave); $tw->insert('end', $item, $tagname); $tw->insert('end', "\n"); } MainLoop; sub clicked_item { my ($item) = @_; print "You clicked on item $item!\n"; }

    I hope that will help you to get started.

    Update:  Separated the text insert into two lines, so that the tag only applies to the text, not to the rest of the blank line.


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: TK question: navigating frames
by zentara (Cardinal) on Sep 21, 2006 at 15:30 UTC
    Hi, I would use a listbox on the left, and text widget on the right. The only glitch is that a left click on a listbox is predefined to select an item, so I made a right-click to actually open the file.

    P.S. I see you want to draw figures on the right, so make it a canvas and do what you need to do.

    #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = Tk::MainWindow->new( -title => 'Left-click -> select ... Righ +t-click -> view' ); my $frame = $mw->Frame()->pack(); my @files = get_sub_dirs('.'); my $lb = $frame->Scrolled('Listbox', -listvariable => \@files, -scrollbars => 'osoe', #only if needed )->pack(-side => 'left', -fill=>'y',-expand =>1); my $text = $frame->Scrolled('Text', -scrollbars => 'osoe', #only if needed )->pack(-side => 'right'); $lb->bind( '<ButtonPress-3>', [ \&view_it, Ev('@') ] ); MainLoop; sub view_it { my ( $lb, $xy ) = @_; $lb->selectionClear( 0, 'end' ); my $index = $lb->index($xy); my $file; if ( defined($index) ) { $lb->selectionSet($index); $file = $lb->get($index); $text->delete('1.0','end'); #clear out old file my $buf; open (FH,"< $file"); read( FH, $buf, -s FH ); close FH; $text->insert('end', $buf); } } ################################################################## sub get_sub_dirs { my $dir = shift; opendir my $dh, $dir or die "Error: $!"; my @files = grep !/^\.\.?$/, readdir $dh; closedir $dh; @files = grep ! -d, @files; return @files; }

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
Re: TK question: navigating frames
by rcseege (Pilgrim) on Sep 22, 2006 at 01:24 UTC

    Update: Nevermind about DirTree -- it probably isn't what you want, despite appearances to the contrary -- at least, it's not as flexible as I remembered. Of the three I mentioned, probably HList is the best bet. However, it's pretty discouraging after all this time to still find the bindings to be faulty despite several submitted patches... still, if you use "single" selectmode, then browsecmd should work Ok.

    Three different developers, three different choices for the widget used for mavigation in the left pane. In addition to looking at Tk::Listbox and Tk::Text, I would also suggest you consider one of the HList widgets (Tk::HList, Tk::Tree, or Tk::DirTree) - Tk::DirTree, in particular.

    HList, Tree, and DirTree all feature the -browsecmd option which can be used to define a callback when a user browses through entries. DirTree allows you to specify the directory using the -directory option which will populate the DirTree widget for you.

    DirTree should simplify the population of the widget entries, and the binding as well, compared to the other approaches, though all of the mentioned approaches should work fine. You might even consider trying all three as an introduction to learning Tk.

    Side note to liverpole: that was a nice intro to Text tags (++).

    Rob