instalar como python menu contextmenu pygtk

python - como - pip install gtk 3



El elemento del submenú no llama a la función (2)

#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()

Mi elemento de nivel superior "Item2" llama a la función definida "callBackFunction". Pero, ¿por qué "elemento de submenú" no ? ¿Qué estoy haciendo mal?

EDITAR

He aquí cómo he logrado forzar a los elementos del submenú a que realicen una acción deseada:

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

Pero todavía no entiendo por qué el evento "activar" no funciona en los elementos del submenú, mientras que funciona en los elementos del menú de nivel superior


Es un problema inherente con el enfoque del submenú explicado aquí :

el submenú no se enfoca hasta que se hace clic en el elemento del menú al que está conectado (aunque el submenú aparece cuando el mouse está sobre el elemento del menú).

El resultado es que los elementos del submenú no emiten la señal de activación a menos que se haga clic primero en el elemento del menú principal.

Esto explica por qué la navegación con el teclado parece funcionar.

He estado trabajando en este problema durante más de un año, y no conozco ninguna solución para él, solo el "button-press-event" que ha descubierto.


Mientras que "button-press-event" funciona, tiene algunos inconvenientes:

  • No funciona para la navegación con solo teclado
  • Si la devolución de llamada bloquea, todo el Servidor X está bloqueado (ver gPodder bug 1778 )

Para mi propia aplicación (gPodder), he solucionado esto en commit a09b204a .

Lo que nosotros queremos:

  1. Reacciona a la señal de "activate" (para navegación por el teclado y para situaciones donde también se hace clic en el elemento del menú principal)
  2. Reacciona a la señal de "button-press-event" (para evitar el error)
  3. Ejecute la devolución de llamada en la siguiente iteración del ciclo principal (para evitar el bloqueo del Servidor X)
  4. Asegúrese de que la devolución de llamada solo se realice una vez ( "activate" y "button-press-event" pueden ocurrir en algunas circunstancias)

Para 1. y 2. simplemente podemos conectarnos a ambas señales. Para 3. podemos usar gobject.idle_add() . Para 4. podemos usar un threading.Semaphore .

Esto da como resultado el siguiente código:

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)

Ahora puede usar esto en su código de la siguiente manera: en lugar de llamar a uno de:

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

Usted llama esto en su lugar:

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

Además, archivó el error 695488 en GNOME Bugzilla.