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

Greeting esteemed monks,

I'm trying to set a popup menu in a Gtk2::TreeView which can have different menu choices depending on the type of information in the row selected by the user.

The first time selecting the popup menu is fine according to the data it sees. The next time I select a row with data that requires a different popup it continues to show the old popup in addition to the new one.

I just can't seem to clear the menu.

Any ideas?

Code snippet

sub popup { my $menu; if ($type eq 'type1') { $menu = Gtk2::Menu->new(); my $menu_item = Gtk2::MenuItem->('Properties'); $menu_item->signal_connect(activate => sub { # do something }); $menu->append($menu_item); }elsif ($type eq 'type2') { $menu = Gtk2::Menu->new(); my $menu_item = Gtk2::MenuItem->('View'); $menu_item->signal_connect(activate => sub { # do something else }); $menu->append($menu_item); } $simple_list =>signal_connect('button-press-event' => sub { my ($widget, $event) = @_; return FALSE unless $event->button eq 3; $menu->popup ( undef, undef, undef, undef, $event->button, $event->time); } $menu->show_all; }

Replies are listed 'Best First'.
Re: TreeView popup issue
by zentara (Cardinal) on Oct 26, 2009 at 17:50 UTC
    Hi, i'm a little rusty, but I think you will have to either make a separate menu for each item, or dynamically load the menu items from a hash or something. Gtk2 is very good about cleaning up menus that are self contained in a sub.... so don't feel bad about using the menu once then letting it be discarded....here is a cheap fast example

    what I would do if I had more time to play around, is to have a hash containing your values( or maybe pulled from a db)..... then as you build your menu, plug in the values you need. Another thing to try is $menu->destroy your menu after each use, so the old global dosn't get left laying around..... watch for memory gains too as you run alot of menu calls.

    As you can see from the code, you can get the button the menu is being called from, from the callback arguments being passed in..... so that gives you your way of loading a custom menu for the button in question.

    One last point, I didn't use a treeview for my example, but what might be happening, is that your menu is attached to the treeview itself, not the elements. Remember, labels( common in treeview), don't respond to events.... you may need event boxes for each label to signal_connect to.

    #!/usr/bin/perl use warnings; use strict; use Glib ':constants'; use Gtk2 'init'; my $w = Gtk2::Window->new('toplevel'); $w->signal_connect(destroy => sub { Gtk2->main_quit() }); $w->set_border_width(12); $w->show(); my $vbox = Gtk2::VBox->new( FALSE, 6 ); $w->add($vbox); my $b = Gtk2::Button->new_from_stock('gtk-ok'); $vbox->pack_start( $b, FALSE, FALSE, 0 ); $b->signal_connect(clicked => sub { $w->destroy() }); my $b1 = Gtk2::Button->new_from_stock('gtk-cancel'); $vbox->pack_start( $b1, FALSE, FALSE, 0 ); $b1->signal_connect(clicked => sub { }); $b->signal_connect(button_release_event => sub { my ($button, $event) = @_; return FALSE if $event->button != 3; my $item; my $menu = Gtk2::Menu->new(); $item = Gtk2::MenuItem->new_with_mnemonic('Item _1'); $menu->append($item); $item->show(); $item = Gtk2::MenuItem->new_with_mnemonic('Item _2'); $menu->append($item); $item->show(); $item = Gtk2::SeparatorMenuItem->new(); $menu->append($item); $item->show(); $item = Gtk2::MenuItem->new_with_mnemonic('Item _3'); $menu->append($item); $item->show(); $menu->popup(undef, undef, undef, undef, $event->button, $event->time); return TRUE; }); $b1->signal_connect(button_release_event => sub { my ($button, $event) = @_; return FALSE if $event->button != 3; my $item; my $menu = Gtk2::Menu->new(); $item = Gtk2::MenuItem->new_with_mnemonic('Z_1'); $menu->append($item); $item->show(); $item = Gtk2::MenuItem->new_with_mnemonic('Z_2'); $menu->append($item); $item->show(); $item = Gtk2::SeparatorMenuItem->new(); $menu->append($item); $item->show(); $item = Gtk2::MenuItem->new_with_mnemonic('Z_3'); $menu->append($item); $item->show(); $menu->popup(undef, undef, undef, undef, $event->button, $event->time); return TRUE; }); $w->show_all; Gtk2->main(); 0;

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku
Re: TreeView popup issue
by biohisham (Priest) on Oct 26, 2009 at 13:31 UTC
    I faced a similar situation with a Tk application,so I introduced a refresh button that checks if the pop-up menu already exists and destroys it before invoking another pop-up menu.. Maybe you would prefer to:
    • look at where the pop-up menus are called from.
    • destroy any existing pop-menus from these places before they invoke their specific pop-menu.


    Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind.
Re: TreeView popup issue
by Anonymous Monk on Oct 27, 2009 at 00:35 UTC
    Thanks for the responses. It will give me another avenue to investigate.