Book HomeMastering Perl/TkSearch this book

15.8. Synthesizing Virtual Events

Tk supports a generic event command to define, generate, query, and delete virtual events. These are events that we make (or are made on our behalf) above and beyond those in Tk. We've mentioned the eventGenerate method previously, which generates events just as if they'd come from the window system. Using eventGenerate, we can simulate a person typing characters and clicking buttons, as well as invoking other real and virtual events.

The following code "types" the characters "Hello Perl/Tk" in the Entry widget $e. It's important to note that the Entry widget must have the keyboard focus, otherwise the data falls into the bit bucket. The update command is also important, as it ensures that all events have been processed. $evar is the Entry's -textvariable and, if all goes well, it will contain the "typed" characters.

my %keysyms = (' ' => 'space', '/' => 'slash');
my $evar;
my $e = $mw->Entry(-textvariable => \$evar)->pack;

$b = $mw->Button(
    -text    => 'Show $evar',
    -command => sub {print "$evar\n"},
)->pack;

$e->focus;
$mw->update;			# prevents lost characters

Figure 15-8 shows the outcome.

Figure 15-8

Figure 15-8. Data synthesized by eventGenerate

Here's the input loop. Most of the characters in the string "Hello Perl/Tk" are their own keysyms, but for those that aren't, we provide a mapping through the hash %keysysms.

foreach (split '', 'Hello Perl/Tk') {
    $_ = $keysyms{$_} if exists $keysyms{$_};
    $e->eventGenerate('<KeyPress>', -keysym => $_);
    $mw->idletasks;
    $mw->after(200);
}

After a short delay, we enter the Button's space, press it, and release it. The release event invokes the Button's callback, which prints "Hello Perl/Tk".

$mw->after(1000);

$b->eventGenerate('<Enter>');
$b->eventGenerate('<ButtonPress-1>');
$b->eventGenerate('<ButtonRelease-1>');

We create a virtual event using eventAdd. Once a virtual event is defined, we must create an actual binding to trigger the event. The following code creates the virtual event <<Gromit>>. Notice that virtual event names are surrounded by double angle brackets to distinguish them from real event names.

The <<Gromit>> virtual event is bound to the real event, <KeyPress>. Once defined, we bind <<Gromit>> to the subroutine look_for_gromit, which simply searches for the string "Gromit" (in this case, from an Entry widget).

We call bindDump and eventInfo to display interesting binding and event information.

my $e = $mw->Entry->pack;
$e->focus;
$e->eventAdd('<<Gromit>>' => '<KeyPress>');
$e->bind('<<Gromit>>' => \&look_for_gromit);

&bindDump($e);
print $e->eventInfo, "\n";

sub look_for_gromit {
    my $text = $_[0]->get;
    print "Found Gromit in '$text'\n" if $text =~ /Gromit/i;
}		    

Figure 15-9 shows the Entry and what we typed in it.

Figure 15-9

Figure 15-9. Searching for Gromit

As soon as we type the t and ! characters, look_for_gromit prints this:

Found Gromit in '123gROMit'
Found Gromit in '123gROMit!'

This is an excerpt from the bindDump output, showing the Entry widget's instance bindings.

2. Binding tag '.entry' has these bindings:
                    <<Gromit>> : Tk::Callback=ARRAY(0x82d5160)
                                   CODE(0x8270928)

The eventInfo method can return the event descriptor(s) associated with a virtual event. If no virtual event is specified, it returns a list of all virtual events.

<<LeftTab>><<Copy>><<Gromit>><<Undo>><<Cut>><<Redo>><<Paste>>

There's also an eventDelete method to remove an event descriptor from a virtual event or delete a virtual event entirely.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.