in reply to (bbfu) (here's an example) Re: perl tk popup menu
in thread perl tk popup menu

Great! Thank you so much. One additional quick question, although I think this question is more involved. It would seem to me that I could save memory by only creating one popup menu and dynamically setting the values in it based on where in my application the user right clicked.

For example. Let's say I have 40 label widgets in a grid, and I want the user to be able to right click on any one of the label's and the menu would then contain the text from that label in the buttons of the menu. I can use the postcommand option easily enough to reconfigure the menu, but the problem would be knowing what label was under the mouse when the user right clicked. Is there a way to do that without making a big mess?

Of course I could make a different menu for each label, and bind the menu just to the given label widget, but that would use more memory. I'd rather optimize for space than speed in this case, but seeing as I'm already doing perl and tk, maybe saving memory is a lost cause...
Thanks for your help and any future info!
  • Comment on Re: (bbfu) (here's an example) Re: perl tk popup menu

Replies are listed 'Best First'.
(bbfu) (reusing menus) Re2: (bbfu) (here's an example) Re: perl tk popup menu
by bbfu (Curate) on Nov 09, 2001 at 04:06 UTC

    I'd say, especially if your menu will contain mostly the same stuff except for the label text, you should definately re-use the popup menu. Update: Though, if your menus are going to be completely different depending on where the user clicked, it would probably make more sense to pre-generate all the menus. Unless you have a lot of them. I guess, uh, it just depends. ;-)

    As for how to tell what label was under the mouse, just use the 'W' parameter to Ev(), like so:

    # this is all documented under Tk::bind $mw->bind('<3>', [\&callback, Ev('X'), Ev('Y'), Ev('W')]);

    ...and it should pass you a reference to the widget that was clicked upon (as the fourth parameter).

    Update: Oh, and, uh, you'd have to alter the menu within the callback that shows it (just before posting) because I don't know of an easy way to pass an argument (ie, the clicked widget) to the postcommand() method.

    Update2: Uh, like this: :-)

    #!/usr/bin/perl use Tk; use Tk::Menu; $mw = MainWindow->new(); $menu = $mw->Menu(-tearoff => 0); $menu->add('separator'); $menu->add('command', -label => 'One', -command => \&item1); $menu->add('command', -label => 'Two', -command => \&item2); $mw->Label(-text => 'Label 1')->pack(); $mw->Label(-text => 'Label 2')->pack(); $mw->Label(-text => 'Label 3')->pack(); $mw->bind('<3>', [\&showmenu, Ev('X'), Ev('Y'), Ev('W')]); $mw->focus(); MainLoop; sub showmenu { my ($self, $x, $y, $widget) = @_; my $label = $widget->cget('text'); $menu->insert(0, 'command', -label => $label, -command => sub { print "Clicked $label.\n" }, ); $menu->post($x, $y); $menu->delete(0,0); } sub item1 { print "Item 1!\n" } sub item2 { print "Item 2!\n" }

    bbfu
    Seasons don't fear The Reaper.
    Nor do the wind, the sun, and the rain.
    We can be like they are.

Re^2: (bbfu) (here's an example) Re: perl tk popup menu
by Anonymous Monk on Feb 12, 2008 at 18:00 UTC
    I tried the example Perl code. In order to make it work, I had to make three changes:
  • change the hashbang line from #!/usr/bin/perl to #!/usr/bin/env perl
  • change the cget() call from cget('text') to cget('-text')
  • change the insert() call from insert(0,...) to insert(1,...)