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

I have the following snippet of Perl/Tk code:
$lb->tagConfigure ('cr_link', -foreground => "red"); $lb->tagBind ('cr_link', "<Button-1>",\&show_cr);
I have applied this tag to various words in my text widget. When someone clicks on one of these words and the callback gets called, how do I get the value of the text that they clicked on? - TIA, - Jim

Replies are listed 'Best First'.
Re: Using Perl/Tk text tags
by Baboon (Acolyte) on Jun 14, 2002 at 16:49 UTC
    tagPrevrange is exactly what you're searching for. Check in documentation for it and use it in conjunction with 'current' tag which means current mouse position. So you need following (unchecked but taken out from my working program) code:
    $text->tag('bind','your-tag','<Button-1>'=>sub { my $var = $text->get($text->tagPrevrange('your-tag','current')); # and here do something with $var });

    Also, 'widget' program, which comes with Tk distribution, greatly helps to answer similar questions, because it allows you to see a code that implements a behaviour that is currently demonstrated.

    update: 'current' is a *mark* and not a tag

    Best wishes,
    I.R.Baboon.

      Exactly what I needed. Thank you very much.
Re: Using Perl/Tk text tags
by BlueBlazerRegular (Friar) on Jun 14, 2002 at 16:29 UTC

    In the interests of TIMTOWTDI, here is another example. This one will display the line or the word associated with the click on tag, depending upon which how the tags were set. In your case, since you've mentioned that you are setting the tags to various words, I would use the word logic, but I included the code for selecting entire lines as well as it is odd enough to be worth mentioning.

    Without further ado, here is the code:

    #!/usr/bin/perl -w use strict; use Tk; # # Create the main window and stick the widgets in it... # my $mw = MainWindow->new(); $mw->geometry("600x300"); my $one_F = $mw->Frame( )->pack(-side => 'top', -fill => 'x', -expand => 1, -padx => 3, -pady => 3, ); my $two_F = $mw->Frame( )->pack(-side => 'top', -fill => 'x', -expand => 1, -padx => 3, -pady => 3, ); $mw->Label(-text => "Selected Text ->", )->pack(-side => 'left', -in => $one_F, ); my $selected = ""; $mw->Entry(-textvariable => \$selected, )->pack(-side => 'left', -in => $one_F, ); my $tb = $mw->Scrolled("Text", -wrap => 'none', )->pack(-side => 'left', -in => $two_F, -expand => 1, -fill => 'both', ); # # Define the 'red' tag # $tb->tagConfigure('hl', -foreground => "red", ); $tb->tagBind('hl', "<Button-1>", sub{ ( $selected ) = &Select_Text( $tb, 'hl', 'line' ) +; }, ); # # Define the underline tag # $tb->tagConfigure('ul', -underline => 1, ); $tb->tagBind('ul', "<Button-1>", sub{ ( $selected ) = &Select_Text( $tb, 'ul', 'word' ) +; }, ); # # Add a bunch of repetitive lines to the text box, assigning some to # tags... # for ( 1 ..100 ) { $tb->insert("$_.0", "This is line # $_\n" ); if ( $_ % 5 == 0 ) { $tb->tagAdd('hl', "$_.0 linestart", "$_.0 lineend" ); } if ( $_ % 3 == 0 ) { $tb->tagAdd('ul', "$_.8", "$_.12" ); } } MainLoop(); exit 0; # # Get the text that is assigned to the tag. # sub Select_Text { my( $tb, $tag, $type ) = @_; my $selected = ""; if ( $type eq "line" ) { chomp( $selected = $tb->get( $tb->tagNextrange("$tag", "current -1 lines +" ) ) ); } elsif ( $type eq "word" ) { chomp( $selected = $tb->get( $tb->tagNextrange("$tag", "current wordstar +t" ) ) ); } return( $selected ); }

    This was run on Win NT, using ActiveState Perl 5.6.1. This code will handle you having multiple words assigned to the same tag - it probably won't handle you assigning half a word to one tag and the other half to another tag.

    Hopefully this helps. Even if you don't use it, I still enjoyed the challenge...

    Pat

Re: Using Perl/Tk text tags
by {NULE} (Hermit) on Jun 14, 2002 at 15:29 UTC
    Hi,

    I can't see enough from your example to know if this will really help you. But the easiest thing to do is pass your text to your subroutine the bind method:

    $lb->tagBind ('cr_link', "<Button-1>", [ \&show_cr, "cr_link" ]);
    This may not work if you have multiple items tagged with 'cr_link'. To work around that you might have to loop through all of your items with that tag and bind them seperately so when the callback occurs you can tell them apart.
    #psuedo code my $i = 0; my $h = {}; for (@tags) { $lb->tagConfigure("cr_link$i", -options => 'values'); $lb->tagBind("cr_link$i", "<Button-1>", [ \&show_cr, "$i" ]); $h->{$i} = "Something useful here like $text_of_lb->{$i}"; $i++; }

    Again, psuedo-code so YMMV. Hope that helps,
    {NULE}
    --
    http://www.nule.org