#submenu
clearMenu = gtk.Menu()
item = gtk.MenuItem("submenu item")
item.connect("activate", lambda w: self.callBackFunction())
clearMenu.append(item)
item.show()
'''TOP level'''
menu = gtk.Menu()
item = gtk.ImageMenuItem("Item1")
img = gtk.Image()
img.set_from_file('image1.png')
item.set_image(img)
menu.append(item)
item.set_submenu(clearMenu) #attach submenu
item.show()
item = gtk.ImageMenuItem("Item2")
img = gtk.Image()
img.set_from_file('image2.png')
item.set_image(img)
item.connect("activate", lambda w: self.callBackFunction())
menu.append(item)
item.show()
My top level item "Item2" calls defined function "callBackFunction". But why "submenu item" does not? What i'm doing wrong?
EDIT
here is how i've managed to force submenu items kick-in desired action:
item.connect("button-press-event", self.callBackFunction, argument1, argument2)
But i still dont get it why event "activate" does not works on submenu items, while works in top level menu items
While "button-press-event"
works, it has a few drawbacks:
For my own application (gPodder), I've worked around this in commit a09b204a.
What we want:
"activate"
signal (for keyboard navigation and for situations where the parent menu item is also clicked)"button-press-event"
signal (to work around the bug)"activate"
and "button-press-event"
can both happen in some circumstances)For 1. and 2. we can simply connect to both signals.
For 3. we can use gobject.idle_add()
.
For 4. we can use a threading.Semaphore
.
This results in the following code:
import threading
import gobject
def submenu_item_connect_hack(menu_item, callback, *args_for_callback):
only_once = threading.Semaphore(1)
def handle_event(item, event=None):
if only_once.acquire(False):
gobject.idle_add(callback, *args_for_callback)
menu_item.connect('button-press-event', handle_event)
menu_item.connect('activate', handle_event)
You can now use this in your code as follows: Instead of calling one of:
item.connect("activate", lambda w: self.callBackFunction())
item.connect("button-press-event", self.callBackFunction, argument1, argument2)
You call this instead:
submenu_item_connect_hack(item, self.callBackFunction, argument1, argument2)
Also, filed bug 695488 in GNOME Bugzilla.
It's an inherent problem with submenu focus explained here:
the submenu doesn't get focus until the menu item it's attached to is clicked (even though the submenu appears when the mouse is over the menu item.)
The upshot is that items in the sub menu don't emit the activate signal unless the parent menu item is clicked first.
This explains why keyboard navigation seems to work.
I've been working around this problem for more than a year, and I don't know of any solution to it — just the "button-press-event"
workaround you've discovered.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With