in reply to Tk Scrolled textbox, parse on input?

All what you need is to be able to capture key release event, and the key pressed. This demo shows you the way:

use Tk; use strict; use warnings; my $mw = new MainWindow(title => "demo"); my $entry = $mw->Entry(width => 20)->pack; $entry->bind("<KeyRelease>", [sub {print $_[1];}, Ev('A')]); MainLoop;

Replies are listed 'Best First'.
Re: Re: Tk Scrolled textbox, parse on input?
by Elijah (Hermit) on Dec 08, 2003 at 04:37 UTC
    Yes this looks like the right teack however I tried to modify it to do what I wanted but get an error when I try to split $_
    use Tk; use strict; use warnings; my $mw = new MainWindow(title => "demo"); my $entry = $mw->Scrolled("Text", -scrollbars => 'e', -font => '12')-> +pack(-side => 'bottom', -fill => 'both', -expand => 1); #$entry->bind("<KeyRelease>", [sub {print $_[1];}, Ev('A')]); $entry->bind("<KeyRelease>", [\&color, Ev('A')]); $entry->tagConfigure("blue", -foreground => "blue"); MainLoop; sub color { my $count = 0; my @char = split(//, $_); my @word = split(/ /, $_); foreach my $char (@char) { $count++; } foreach my $word (@word) { if ($word =~ /color/) { my $len = length($word); my $from = "1\.$count"; my $next = $from + $len; $entry->tagAdd("blue", $from, $next); } } }
    The error says that $_ is not initialized but $_1 is? Why is this so and how can I accomplish what I want to do in this sub if I cannot use $_?

      $_ is not the same as $_[1]. See perlvar for the complete details. In this instance, $_[1] contains the key that was released and $_ truly is uninitialized. However, neither $_ nor $_[1] are going to help you do what you want.

      Look instead to the Tk documentation for the get widget method. It will allow you to "get" the text from the scrolled text widget. (Oh and you'll have to fix the logic for your tag coloring to work with multiple lines.)

      Good luck!

        You said something I wanted to say. When replies from other monks give one quick remedies, it is always a good idea to read document on one's own to get the big picture and a deeper understanding.

        In this case, I would add two documents in addition to what you have just mentioned: callbacks and bind under Tk.

        I know I will have to re-work the logic for multiple lines but it has to work with one line before it can work on multiple lines. Once I get it the way I want it on one line it will be easy to convert the code to support multiple lines. I was aware of the get() method but wanted to try and avoid this seeing how if the source code being worked on is a few hundred lines or so I will be calling get on the entire textfield every time a new character is entered. This could cause serious performance issues down the road. Maybe a get("1.0:, "lineend") will be better than a get("1.0", "end"). I have tried the lineend before but it has never worked. Maybe I should revisit it.

      $_[1] is initialized, as you passed a parameter to sub color(), which takes Ev('A') containing the value of the last key stroke.

      "how can I accomplish what I want to do in this sub if I cannot use $_?"

      Why cannot you? That's you code, and you can always modify it to work ;-) I believe that you expect $_ to contain (part of) the content in your text box. You can always call get() method of the text box to get the content at certain position or a range of positions.

      Slightly modified your code to demo a little bit more: (Played with this code, and I do see some text colored blue. Hey, that's mainly your code!)

      use Tk; use strict; use warnings; my $mw = new MainWindow(title => "demo"); my $entry = $mw->Scrolled("Text", -scrollbars => 'e', -font => '12')-> +pack(-side => 'bottom', -fill => 'both', -expand => 1); #$entry->bind("<KeyRelease>", [sub {print $_[1];}, Ev('A')]); $entry->bind("<KeyRelease>", [\&color, Ev('A')]); $entry->tagConfigure("blue", -foreground => "blue"); MainLoop; sub color { my $content = $entry->get("1.0", "end"); my $count = 0; my @char = split(//, $content); my @word = split(/ /, $content); foreach my $char (@char) { $count++; } foreach my $word (@word) { if ($word =~ /color/) { my $len = length($word); my $from = "1\.$count"; my $next = $from + $len; $entry->tagAdd("blue", $from, $next); } } }

      You still have to do some work to implement your application logic, but I have already given you the right tool. Have fun!