I'm looking at Wx just kind of as a way to teach myself a bit of something new ... and I'm stuck. Really early, too. *sigh* What I'm trying to do is create a frame with naught but a menu and a multi-line text box. The menu should include the standard "cut", "paste", etc. So, I started hooking stuff in to try, but found that as soon as I hook in the Paste menu item, for example, it stops working. That is, if I don't add that item to the menu, I can paste with Ctrl-V just fine. But when I try to hook up the menu item, that stops working. And I can't seem to set an EVT_MENU for it, either, at least not pointing directly to the Paste method of the Wx::TextCtrl object.

Ok, there's what the problem is - here's the code I'm using:

#!/usr/bin/perl use strict; use warnings; use Wx; use Smart::Comments '###'; package WxPMEdit; use base 'Wx::App'; use Wx qw( wxDEFAULT_FRAME_STYLE ); sub OnInit { my $self = shift; my($frame) = WxPMFrame->new( undef, # parent -1, # ID (-1 = don't care) "wxPMTest", # title [-1,-1], # position (don't care) [500,300], # size wxDEFAULT_FRAME_STYLE, # window name? not really sure what this + is ); $frame->Show(1); return 1; # success } package WxPMText; use base 'Wx::TextCtrl'; use Wx qw( wxTE_MULTILINE ); sub new { my $class = shift; ### assert: @_ >= 3 $_[3] ||= [-1,-1]; $_[4] ||= [-1,-1]; $_[5] |= wxTE_MULTILINE; my $self = $class->SUPER::new(@_); # this doesn't work... so have to hack the parameters (see above) # $self->SetStyle(Wx::TextCtrl::wxTE_MULTILINE); $self; } package WxPMFrame; use base 'Wx::Frame'; use Wx::Event; use Wx qw( wxID_EXIT wxID_CUT wxID_COPY wxID_PASTE wxID_UNDO wxID_REDO ); my @menu = ( [ '&File', [ -1, "&Open\tCtrl-O", 'Open' ], '-', [ wxID_EXIT, "E&xit\tCtrl-Q", 'Exit' ], ], [ '&Edit', [ wxID_UNDO, "&Undo\tAlt", 'Undo' ], #{ menuitem => [ wxID_UNDO, "&Undo\tAlt", 'Undo' ], object => ' +_text', method => 'Undo' }, [ wxID_REDO, "&Redo\tCtrl-Alt", 'Redo' ], '-', #[ wxID_CUT, "Cu&t\tCtrl-X", 'Cut' ], #[ wxID_COPY, "&Copy\tCtrl-C", 'Copy' ], { menuitem => [ wxID_PASTE, "&Paste\tCtrl-V", 'Paste' ], object + => '_text' }, #[ wxID_PASTE, "&Paste\tCtrl-V", 'Paste' ], [ -1, "Select &All\tCtrl-A", 'Select All' ] ], ); sub _SetupMenu { my $self = shift; my $menubar = Wx::MenuBar->new(); for my $top_menu (@menu) { my $menu = Wx::Menu->new(); $menubar->Append($menu, shift @$top_menu); for (@$top_menu) { if (ref $_) { # we may have an array ref, or a hash ref (with the ar +ray ref # inside) my $data = ref $_ eq 'ARRAY' ? { menuitem => $_ } : $_ +; my $item = $data->{menuitem}; my $id = #$self->{_menu}{$item->[2]} = $menu->Append(@$item)->GetId(); # look for the handler - with fallback my $func = $data->{method} || $item->[2]; # who will handle? my $object = $data->{object} || $self; $object = $self->{$object} if not ref $object; # how do we do this? my $code = $func; if (ref $code or $code = $object->can($func) or $code = $object->can(do { ($func = 'OnMenu' . $fun +c) =~ s/\s+//g; $func }) ) { $Data::Dumper::Deparse = 1; ### setup menu: $object ### id: $id ### code: $code ### func: $func Wx::Event::EVT_MENU($object, $id, $code); } else { warn "$item->[2] not implemented\n"; } } elsif ($_ eq '-') { $menu->AppendSeparator(); } else { die "bad data in \@menu"; } } } $self->SetMenuBar($menubar); } sub new { my $class = shift; my $self = $class->SUPER::new(@_); $self->{_text} = WxPMText->new($self, -1, ''); $self->{_text}->SetFocus; $self->_SetupMenu; $self } sub OnMenuOpen { my $self = shift; print "OnMenuOpen stub"; } sub OnMenuUndo { my $self = shift; $self->{_text}->Undo(); } sub OnMenuRedo { my $self = shift; $self->{_text}->Redo(); } sub OnMenuPaste { my $self = shift; ### pasting $self->{_text}->Paste(); ### paste code: $self->{_text}->can('Paste') } sub OnMenuExit { my $self = shift; $self->Close(1); } sub OnMenuSelectAll { my $self = shift; $self->{_text}->SetSelection(-1,-1); } package main; my $app = WxPMEdit->new(); $app->MainLoop(); 0;
Now, if I run this, Shift-Insert still pastes, but Ctrl-V doesn't. If I comment out the wxID_PASTE line, Ctrl-V starts working (but, of course, it's not in the menu). If I uncomment the following line, it works, but goes through the extra layer of the OnMenuPaste function in my Frame - which seems silly and excessive. I'd hate to have to have a sub for each menu item when all it's doing is forwarding, even if the subs are anonymous.

I must be missing something - so I'm hoping others can help here. If you don't have Smart::Comments installed, just comment out the line that uses it :-)

As you can see - I like data-driven programming - the menu is all in a list, and then I iterate over it to populate everything. I'm sure it'll get refactored again later if I start playing with events other than menu events.


In reply to Wx: Passing events by Tanktalus

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.