Skip Menu |

This queue is for tickets about the Tk CPAN distribution.

Report information
The Basics
Id: 4803
Status: open
Worked: 1 hour (60 min)
Priority: 0/
Queue: Tk

People
Owner: Nobody in particular
Requestors: rcaputo [...] pobox.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: (no value)
Fixed in: (no value)



Date: Thu, 1 Jan 2004 00:36:09 -0500
From: Rocco Caputo <rcaputo [...] pobox.com>
To: poe [...] perl.org
CC: bug-Tk [...] rt.cpan.org
Subject: Re: Tk With POE - bind() function for keypresses
On Wed, Dec 31, 2003 at 01:00:05PM +0000, James Brown wrote: Show quoted text
> Hi All, > > I need a bit of help here. I'm trying get keyboard input (under UNIX > and Windows) into a POE app which I'm developing. Having tried Curses > and ReadLine, which work fine on UNIX, but won't install on Windows, I > think I'll have to explore the POE-Tk route. > > I've managed to get the code working without POE, but (being new to POE) > I struggle to understand how to use the postback() and bind() functions. > > ...etc...
[...] Show quoted text
> Basically, I see this error: > > Tk::Error: Can't call method "XEvent" on unblessed reference at **line > 79.**Tk::After::once at D:/perl/site/lib/Tk/After.pm line 83 > [once,[{},after#43,0,once,[\&POE::Kernel::_loop_event_callback]]] > ("after" script) > > I think my problem is that when the keypress event occurs, the "ev_key" > happens, but I'm not so sure of how to extract the parameters that Tk > would normally send along with this event.
Tk is not passing the event information to POE. As you know, postbacks are anonymous subroutine references that post POE events when they're called. They're used as a thin, flexible interface between POE and Tk, among other things. Postbacks are blessed, and their DESTROY methods are used to notify POE when Tk is done with them. From Tk's point of view, the only difference between a callback and a postback is this blessing. For some reason, Tk does not pass parameters to a blessed callback. To demonstrate: #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = Tk::MainWindow->new(); my $sub = \&callback; $mw->bind("<Any-KeyPress>" => $sub); Tk::MainLoop(); exit 0; sub callback { warn "@_"; } displays Tk::MainWindow=HASH(0x828b7e4) at tk-callback.perl line 18. A subtle change #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = Tk::MainWindow->new(); my $sub = bless \&callback, "whatever"; $mw->bind("<Any-KeyPress>" => $sub); Tk::MainLoop(); exit 0; sub callback { warn "@_"; } changes the output to Warning: something's wrong at tk-callback.perl line 18. There is a workaround. Tk wants an unblessed callback, so you can hide the blessed one inside a plain one. ##Start Event## sub ui_start { my $pb = $_[SESSION]->postback("ev_key"); $poe_main_window->bind ( '<Any-KeyPress>' => sub { $pb->(@_); } ) } A copy of this message has been Cc'd to <bug-Tk@rt.cpan.org>. -- Rocco Caputo - rcaputo@pobox.com - http://poe.perl.org/
Subject: [cpan #4803] Re: Tk With POE - bind() function for keypresses
To: bug-Tk [...] rt.cpan.org
Date: Mon, 05 Jan 2004 08:27:20 +0000
From: Nick Ing-Simmons <nick.ing-simmons [...] elixent.com>
RT-Send-Cc:
Rocco Caputo via RT <bug-Tk@rt.cpan.org> writes: Show quoted text
>This message about Tk was sent to you by rcaputo@pobox.com <rcaputo@pobox.com> via rt.cpan.org > >Full context and any attached attachments can be found at: ><URL: https://rt.cpan.org/Ticket/Display.html?id=4803 > > >On Wed, Dec 31, 2003 at 01:00:05PM +0000, James Brown wrote:
>> Hi All, >> >> I need a bit of help here. I'm trying get keyboard input (under UNIX >> and Windows) into a POE app which I'm developing. Having tried Curses >> and ReadLine, which work fine on UNIX, but won't install on Windows, I >> think I'll have to explore the POE-Tk route. >> >> I've managed to get the code working without POE, but (being new to POE) >> I struggle to understand how to use the postback() and bind() functions. >> >> ...etc...
What is POE ? Show quoted text
> >Tk is not passing the event information to POE. > >As you know, postbacks are anonymous subroutine references that post POE >events when they're called. They're used as a thin, flexible interface >between POE and Tk, among other things. > >Postbacks are blessed, and their DESTROY methods are used to notify POE >when Tk is done with them. From Tk's point of view, the only difference >between a callback and a postback is this blessing.
Tk's callbacks are also blessed (by Tk), likely we are treading on each others toes. Which version of Tk are you using? (Tk804 is slightly different here to Tk800...) Show quoted text
> >For some reason, Tk does not pass parameters to a blessed callback. To >demonstrate: > > #!/usr/bin/perl > > use warnings; > use strict; > > use Tk; > > my $mw = Tk::MainWindow->new(); > > my $sub = \&callback; > > $mw->bind("<Any-KeyPress>" => $sub); > > Tk::MainLoop(); > exit 0; > > sub callback { > warn "@_"; > } > >displays > > Tk::MainWindow=HASH(0x828b7e4) at tk-callback.perl line 18. > >A subtle change > > #!/usr/bin/perl > > use warnings; > use strict; > > use Tk; > > my $mw = Tk::MainWindow->new(); > > my $sub = bless \&callback, "whatever"; > > $mw->bind("<Any-KeyPress>" => $sub); > > Tk::MainLoop(); > exit 0; > > sub callback { > warn "@_"; > } > >changes the output to > > Warning: something's wrong at tk-callback.perl line 18.
Which is interesting - it has reached your callback, but as you say not passed any args. I would have expected Tk to refuse to call the alien object. Will investigate further... Show quoted text
> >There is a workaround. Tk wants an unblessed callback, so you can hide >the blessed one inside a plain one. > > ##Start Event## > sub ui_start { > my $pb = $_[SESSION]->postback("ev_key"); > $poe_main_window->bind ( > '<Any-KeyPress>' => sub { > $pb->(@_); > } > ) > } > >A copy of this message has been Cc'd to <bug-Tk@rt.cpan.org>.
Turns out when I eventually got round to looking into this that there is explcit code to make it do exactly what you say: if (!sv_isobject(sv)) { if (obj && obj->window) { XPUSHs(sv_mortalcopy(obj->window)); } } Reason is to allow for re-direction bindings like $widgetA->bind('<Some-Event>',[$widgetB,'SomeMethod']); That combined with code that converts a bare sub {} into [sub {}] so that array can be blessed into Tk::Callback results in behaviour you are seeing. The re-direction scheme is quite widely used (for example torn off menus re-direct events to the original menu) and has been documented for years. I briefly considered only skipping the arg if $object->isa('Tk') - but quickly found cases where Tk wasn't the base class. So best I can suggest is that widget will be passed if class has a "well known" (to Tk and POE) method. e.g. Tk could do (as XS code): if ($callback->can('_Tk_passWidget') && $callback->_Tk_passTkWidget($widget)) { # pass widget arg as for non objects } If this would help - get back to me quickly and I will put it in imminent Tk804 release.