Элемент подменю не вызывает функцию [с рабочим решением] - PullRequest
4 голосов
/ 07 марта 2011
    #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()

Мой элемент верхнего уровня "Item2" вызывает определенную функцию "callBackFunction". Но почему «пункт подменю» не ? Что я делаю не так?


EDIT

вот как мне удалось заставить элементы подменю включить желаемое действие:

item.connect("button-press-event", self.callBackFunction, argument1, argument2)

Но я все еще не понимаю, почему событие «activ» не работает с элементами подменю, а работает с элементами меню верхнего уровня

Ответы [ 2 ]

5 голосов
/ 09 марта 2013

Хотя "button-press-event" работает, у него есть несколько недостатков:

  • Не работает для навигации только с клавиатуры
  • Если обратный вызов блокируется, весь X-серверзаблокирован (см. ошибка gPodder 1778 )

Для моего собственного приложения (gPodder) я работал над этим в commit a09b204a .

Что мы хотим:

  1. Реагировать на сигнал "activate" (для навигации с помощью клавиатуры и в ситуациях, когда также нажимается родительский элемент меню)
  2. Реагировать на "button-press-event"сигнал (чтобы обойти ошибку)
  3. Запустить обратный вызов в следующей итерации основного цикла (чтобы избежать блокировки X-сервера)
  4. Убедитесь, что обратный вызов вызывается только один раз ("activate"и "button-press-event" могут произойти в некоторых случаях)

Для 1. и 2. мы можем просто подключиться к обоим сигналам.Для 3. мы можем использовать gobject.idle_add().Для 4. мы можем использовать threading.Semaphore.

Это приводит к следующему коду:

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)

Теперь вы можете использовать это в своем коде следующим образом: Вместо вызова одного из:

item.connect("activate", lambda w: self.callBackFunction())
item.connect("button-press-event", self.callBackFunction, argument1, argument2)

Вы называете это вместо этого:

submenu_item_connect_hack(item, self.callBackFunction, argument1, argument2)

Также, ошибка 695488 в GNOME Bugzilla.

4 голосов
/ 08 марта 2011

Это внутренняя проблема с фокусом подменю , объясненная здесь :

подменю не получает фокус, пока элемент меню, к которому он прикреплен, не будет нажат (даже если подменю появляется, когда мышь находится над элементом меню)

В результате элементы в подменю не издают сигнал активации, если только не щелкнуть по первому элементу меню.

Это объясняет, почему навигация с клавиатуры работает.

Я работал над этой проблемой более года, и я не знаю ни одного решения этой проблемы - только обходной путь "button-press-event", который вы обнаружили.

...