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

Dear Monks, this has been really confusing me. Say we have MainWindow $mw that contains a widget $w. Say that $w belongs to a class that has default bindings for the events <Control-v> and <<Paste>> built in and bound to the same paste routine. Let's say you want to make a paste occur by using the eventGenerate method. For the real event, <Control-v> it appears you can call either $mw->eventGenerate('<Control-v>') or $w->eventGenerate('<Control-v>'). That is, eventGenerate can be called as a method of either the MainWindow or the widget, and it works the same. However, for the virtual event, only $w->eventGenerate('<<Paste>>') will work. trying to generate the virtual event off of the MainWindow ($mw->eventGenerate('<<Paste>>')doesn't do anything.

Here's some complete example code below. Examples 1, 2, and 3, work. Example 4 does not. ???

Example 1.

#!/usr/bin/perl -w use strict; use Tk; my $mw = MainWindow->new; $mw->Button(-text => "Paste", -command => \&DoPaste)->pack(); my $t = $mw->Text(-width => 30, -height => 5)->pack(); $t->focus; sub DoPaste { print "DoPaste\n"; $t->eventGenerate('<Control-v>'); } Tk->MainLoop;

Example 2

#!/usr/bin/perl -w use strict; use Tk; my $mw = MainWindow->new; $mw->Button(-text => "Paste", -command => \&DoPaste)->pack(); my $t = $mw->Text(-width => 30, -height => 5)->pack(); $t->focus; sub DoPaste { print "DoPaste\n"; $mw->eventGenerate('<Control-v>'); } Tk->MainLoop;

Example 3 (the virtual event generated off of the widget)

#!/usr/bin/perl -w use strict; use Tk; my $mw = MainWindow->new; $mw->Button(-text => "Paste", -command => \&DoPaste)->pack(); my $t = $mw->Text(-width => 30, -height => 5)->pack(); $t->focus; sub DoPaste { print "DoPaste\n"; $t->eventGenerate('<<Paste>>'); } Tk->MainLoop;

Example 4. Paste button doesn't work. The widget's virtual paste event is not being generated, it seems. If the virtual paste binding weren't tagged with the widget's class then I think it would work. But the real control-v event works regardless. How rude!

#!/usr/bin/perl -w use strict; use Tk; my $mw = MainWindow->new; $mw->Button(-text => "Paste", -command => \&DoPaste)->pack(); my $t = $mw->Text(-width => 30, -height => 5)->pack(); $t->focus; sub DoPaste { print "DoPaste\n"; $mw->eventGenerate('<<Paste>>'); } Tk->MainLoop;

Can anybody explain why this works the way it does. Why generating a virtual event doesn't seem to work the same as generating a 'real' event? My initial impulse is to assume this is a bug, but I make that assumption a lot, and I've never turned out to be right. It's never a bug, I'm just always misunderstanding something. What am I misunderstanding?

Replies are listed 'Best First'.
Re: virtual events and real events with eventGenerate seem to not work the same...
by zentara (Cardinal) on Nov 14, 2007 at 13:49 UTC
    for the virtual event, only $w->eventGenerate('<<Paste>>') will work. trying to generate the virtual event off of the MainWindow ($mw->eventGenerate('<<Paste>>')doesn't do anything.

    Read "perldoc Tk::bind". I'm guessing that since Paste is not an event type for a top level window( where is the Paste supposed to go? ), trying to generate a paste from a $mw is not going to do anything. I'm not sure which syntax is needed to add Paste to the $mw bindings, probably something like

    # untested guess $mw->eventGenerate('Tk::Text','<<Paste>>');
    Maybe someone else knows the trick.

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum

      Maybe it doesn't make sense to call <<Paste>> on a top level, but then why does it work with <Control-v>. I'm willing to bet these two events are bound to the exact same Paste subroutine within the Tk::Text code (but I haven't actually looked, but Tk::TableMatrix is that way).

      I think what Paste is supposed to do isn't really relevant. You could rebind <<Paste>> and <Contol-v> to a subroutine that does nothing more than print "Hello World" to the console, or one could make up a new virtual event and use some unused key sequence event and bind them to a subroutine that just prints "hi". The point is, the window manager seems to treat a virtual event and a physical event in distinctly different ways. I'm just not clear on exactly how different and for what reason.

      My theory at this point is that when you call a virtual event with $w->eventGenerate(<<virtualevent>>), then only the callback for the binding to "virtualevent" that matches widget w$ and it's parent widgets will be called. But when a physcial event is called by $w->eventGenerate(<physicalvent>) then the callback for all bindings to "physicalevent" matching any active widgets contained in $w's toplevel will be called.

      Here are some examples. In the first two examples, since we are generating physical events, all three bindings get called no matter whether the eventGenerate is called by the toplevel $mw, or the text widget $t.

      Example 1

      #!/usr/bin/perl -w use strict; use Tk; my $mw = MainWindow->new; $mw->Button(-text => "Paste", -command => \&DoPaste)->pack(); my $t = $mw->Text(-width => 30, -height => 5)->pack(); $t->focus; $mw->bind('<Control-t>' => \&Print1); $mw->bind('Tk::Text', '<Control-t>' => \&Print2); $t->bind('<Control-t>' => \&Print3); sub DoPaste { $mw->eventGenerate('<Control-t>'); } sub Print1 { my $tw = shift; print "########\n"; print $tw, "\t", ref($tw), "\n"; print "1\n"; print "###########\n"; } sub Print2 { my $tw = shift; print "########\n"; print $tw, "\t", ref($tw), "\n"; print "222222222\n"; print "###########\n"; } sub Print3 { my $tw = shift; print "########\n"; print $tw, "\t", ref($tw), "\n"; print "33333 wheeee!\n"; print "###########\n"; } Tk->MainLoop;

      Example 2 just change $mw->eventGenerate('<Control-t>'); in Example 1 to $t->eventGenerate('<Control-t>');

      Now in Examples 2 and 3 we have replaced Control-t with an arbitrary virtual event name. Otherwise examples 2 and 3 are identical to 1 and 2, respectively. And yet Example 3 only calls the one callback, though Example 4 generates all of them just like Examples 1 and 2..

      Example 3

      #!/usr/bin/perl -w use strict; use Tk; my $mw = MainWindow->new; $mw->Button(-text => "Paste", -command => \&DoPaste)->pack(); my $t = $mw->Text(-width => 30, -height => 5)->pack(); $t->focus; $mw->bind('<<Jayhawk>>' => \&Print1); $mw->bind('Tk::Text', '<<Jayhawk>>' => \&Print2); $t->bind('<<Jayhawk>>' => \&Print3); sub DoPaste { $mw->eventGenerate('<<Jayhawk>>'); } sub Print1 { my $tw = shift; print "########\n"; print $tw, "\t", ref($tw), "\n"; print "1\n"; print "###########\n"; } sub Print2 { my $tw = shift; print "########\n"; print $tw, "\t", ref($tw), "\n"; print "222222222\n"; print "###########\n"; } sub Print3 { my $tw = shift; print "########\n"; print $tw, "\t", ref($tw), "\n"; print "33333 wheeee!\n"; print "###########\n"; } Tk->MainLoop;

      Example 4 just change $mw->eventGenerate('<<Jayhawk>>'); in Example 1 to $t->eventGenerate('<<Jayhawk>>');

      maybe this all much ado about nothing even if my theory is correct, I don't know, it just seems weird, I would have expected virtual events and physcial events to work the same way, and I've never seen anything in the documentation for Tk::bind or Tk::event or Tk::callback that would indicate they shouldn't act the same.

      But they clearly do, right? Or am I crazy? Or did I miss something in the documentation that explains this feathure?