Capítulo 16. Nuevos Controles de PyGTK 2.4

Tabla de contenidos

16.1. Objetos de Acción (Action) y Grupo de Acciones (ActionGroup)
16.1.1. Acciones (Actions)
16.1.2. Grupos de Acciones (ActionGroups)
16.2. Controles de Lista Desplegable (ComboBox) y Lista Desplegable con Entrada (ComboBoxEntry)
16.2.1. Controles ComboBox
16.2.2. Controles ComboBoxEntry
16.3. Controles Botón de Color y de Fuente (ColorButton y FontButton)
16.3.1. Control Botón de Color (ColorButton)
16.3.2. Control Botón de Fuente (FontButton)
16.4. Controles de Entrada con Completado (EntryCompletion)
16.5. Controles de Expansión (Expander)
16.6. Selecciones de Archivos mediante el uso de Controles basados en el Selector de Archivos FileChooser
16.7. El gestor de Interfaces de Usuario UIManager
16.7.1. Perspectiva general
16.7.2. Creación de un gestor UIManager
16.7.3. Adición y Eliminación de Grupos de Acciones (ActionGroups)
16.7.4. Descripciones de la Interfaz de Usuario
16.7.5. Adición y Eliminación de Descripciones de Interfaz de Usuario
16.7.6. Acceso a los Controles de la Interfaz de Usuario
16.7.7. Ejemplo sencillo de Gestor de Interfaz UIManager
16.7.8. Combinación de Descripciones de Interfaz de Usuario
16.7.9. Señales de UIManager

En PyGTK 2.4 se han añadido unos cuantos controles y objetos auxiliares nuevos, incluídos:

16.1. Objetos de Acción (Action) y Grupo de Acciones (ActionGroup)

Los objetos Action y ActionGroup trabajan de forma conjunta para proveer a las aplicaciones de imágenes, texto, retrollamadas y aceleradores a los menús y barras de herramientas. El objeto UIManager utiliza objetos Action y ActionGroup para construir de forma automática dichas barras de menú y herramientas a partir de su descripción en XML. Así, resulta mucho más sencilla la creación y construcción de menús y barras de herramientas mediante UIManager de la manera en la que se describe en una sección posterior. Las secciones que siguen, acerca de los objetos Action y ActionGroup, describen cómo se pueden utilizar éstos directamente, aunque, en su lugar y siempre que sea posible, se recomienda el uso de la clase UIManager.

16.1.1. Acciones (Actions)

Un objeto Action (acción) representa una acción que el usuario puede realizar utlizando la interfaz de una aplicación. Contiene información utilizada por los elementos intermedios de la interfaz (por ejemplo, elementos de menú MenuItem o elementos de barra de herramientas Toolbar) para presentar dicha acción al usuario. Existen dos subclases de la clase Action:

ToggleAction (acción conmutable)

Es una acción Action que permite conmutar entre dos estados.

RadioAction (acción con exclusión)

Una acción Action que puede agruparse de manera que solamente una de ellas puede estar activa.

Por ejemplo, el elemento de menú estándar ArchivoSalir puede ser representado mediante un icono, un texto mnemónico y un acelerador. Cuando se activa, el elemento de menú dispara una retrollamada que podría cerrar la aplicación. De la misma manera, un botón Salir de una barra de herramientas Toolbar podría compartir con aquel el icono, el texto mnemónico y la retrollamada. Ambos elementos de la interfaz podrían ser elementos delegados (proxies) de la misma acción Action.

Los controles de botón normal (Button), botón conmutado (ToggleButton) y botón de exclusión (RadioButton) pueden actuar como delegados (proxies) de una acción (Action), aunque no existe soporte para ellos en la clase UIManager.

16.1.1.1. Creación de acciones

Las acciones Action se crean haciendo uso del constructor:

  action = gtk.Action(name, label, tooltip, stock_id)

name (nombre) es una cadena que identifica la acción (Action) dentro de un grupo (ActionGroup) o en la especificación de un gestor de interfaz (UIManager). label y tooltip son cadenas de texto usadas respectivamente como etiqueta y texto de ayuda en los objetos delegados (proxy). Si label es None entonces stock_id ha de ser una cadena de texto que especifique un elemento de serie (Stock item) del que se obtendrá la etiqueta. Si tooltip es None, entonces la acción (Action) no dispondrá de texto de ayuda.

Como veremos en la sección correspondiente a grupos de acciones (ActionGroups) es mucho más fácil la creación de objetos de acción utilizando algunos métodos de la clase ActionGroup:

  actiongroup.add_actions(entries, user_data=None)
  actiongroup.add_toggle_actions(entries, user_data=None)
  actiongroup.add_radio_actions(entries, value=0, on_change=None, user_data=None)

Más adelante profundizaremos en éstos, aunque primeramente describiremos cómo usar una acción (Action) con un botón (Button) para ilustrar las operaciones básicas necesarias para conectar una acción (Action) a un objeto delegado.

16.1.1.2. Uso de acciones

El procedimiento básico para usar una acción (Action) con un botón (Button) como objeto delegado se ilustra en el programa de ejemplo simpleaction.py. El botón (Button) se conecta a la acción (Action) con el método:

  action.connect_proxy(proxy)

donde proxy es un control delegado del tipo: elemento de menú MenuItem, elemento de barra de herramientas ToolItem o botón Button.

Una acción Action tiene una señal, la señal "activate" que se dispara cuando la acción (Action) se activa, generalmente como resultado de la activación de un control delegado (por ejemplo, cuando se pulsa sobre un botón de una barra de herramientas ToolButton). Simplemente se debe conectar una retrollamada a esta señal para gestionar la activación de cualquiera de los controles delegados.

Este es el código fuente del programa de ejemplo simpleaction.py:

    1   #!/usr/bin/env python
    2
    3   import pygtk
    4   pygtk.require('2.0')
    5   import gtk
    6
    7   class SimpleAction:
    8       def __init__(self):
    9           # Creación de la ventana principal
   10           window = gtk.Window()
   11           window.set_size_request(70, 30)
   12           window.connect('destroy', lambda w: gtk.main_quit())
   13
   14           # Creación de un grupo de aceleradores
   15           accelgroup = gtk.AccelGroup()
   16           # Añadimos el grupo de aceleradores a la ventana principal
   17           window.add_accel_group(accelgroup)
   18
   19           # Creación de una acción para salir del programa usando un elemento de serie
   20           action = gtk.Action('Quit', None, None, gtk.STOCK_QUIT)
   21           # Conexión de una retrollamada a la acción
   22           action.connect('activate', self.quit_cb)
   23
   24           # Creación de un grupo ActionGroup llamado SimpleAction
   25           actiongroup = gtk.ActionGroup('SimpleAction')
   26           # Adición de la acción al grupo con un acelerador
   27           # None significa que se utilice el acelerador el elemento de serie
   28           actiongroup.add_action_with_accel(action, None)
   29
   30           # Hacer que la acción use el grupo de aceleradores
   31           action.set_accel_group(accelgroup)
   32
   33           # Conectar el acelerador a la acción
   34           action.connect_accelerator()
   35
   36           # Crear el botón para usarlo como control delegado para la acción
   37           quitbutton = gtk.Button()
   38           # añadimos el botón a la ventana principal
   39           window.add(quitbutton)
   40
   41           # Conectamos la acción a su control delegado
   42           action.connect_proxy(quitbutton)
   43
   44           window.show_all()
   45           return
   46
   47       def quit_cb(self, b):
   48           print 'Saliendo del programa'
   49           gtk.main_quit()
   50
   51   if __name__ == '__main__':
   52       sa = SimpleAction()
   53       gtk.main()

El ejemplo crea una acción (Action) (línea 20) que usa un elemento de serie que aporta el texto de etiqueta, con un mnemónico, un icono, un acelerador y un dominio de traducción. Si no se usa un elemento de serie, sería necesario especificar en su lugar una etiqueta. La línea 22 conecta la señal "activate" del la acción action al método self.quit_cb() de forma que sea invocado cuando la acción Action es activada por el botón quitbutton. La línea 42 conecta quitbutton a action como control delegado. Cuando se pulsa sobre quitbutton éste activará action y, por tanto, llamará al método self.quit_cb(). El ejemplo simpleaction.py usa bastante código (líneas 15, 17, 31 y 34 para establecer el acelerador del botón). El proceso es similar para los elementos MenuItem y ToolItem.

Figura 16.1, “Ejemplo Simple de Acción” muestra el resultado de la ejecución del programa simpleaction.py.

Figura 16.1. Ejemplo Simple de Acción

Ejemplo Simple de Acción

16.1.1.3. Creación de Controles intermedios (Proxy)

En el apartado anterior previo vimos cómo es posible la conexión de un control existente a una acción (Action) como elemento delegado. En éste veremos como es posible crear un control delegado utilizando los métodos de la clase Action:

  menuitem = action.create_menu_item()

  toolitem = action.create_tool_item()

El ejemplo basicaction.py ilustra una acción Action compartida por un elemento de menú (MenuItem), un botón de barra de herramientas (ToolButton) y un botón ordinario (Button). El elemento de menú (MenuItem) y el botón de la barra de herramientas (ToolButton) se crearán usando los métodos indicados. El código fuente del programa de ejemplo basicaction.py es el siguiente:

    1   #!/usr/bin/env python
    2
    3   import pygtk
    4   pygtk.require('2.0')
    5   import gtk
    6
    7   class BasicAction:
    8       def __init__(self):
    9           # Creación de la ventana principal
   10           window = gtk.Window()
   11           window.connect('destroy', lambda w: gtk.main_quit())
   12           vbox = gtk.VBox()
   13           vbox.show()
   14           window.add(vbox)
   15
   16           # Creación de un grupo de aceleradores
   17           accelgroup = gtk.AccelGroup()
   18           # Adición del grupo a la ventana principal
   19           window.add_accel_group(accelgroup)
   20
   21           # Creación de una acción para salir del programa utilizando un elemento de serie
   22           action = gtk.Action('Quit', '_Quit me!', 'Quit the Program',
   23                               gtk.STOCK_QUIT)
   24           action.set_property('short-label', '_Quit')
   25           # Conexión de una retrollamada a la acción
   26           action.connect('activate', self.quit_cb)
   27
   28           # Creación de un grupo ActionGroup llamado BasicAction
   29           actiongroup = gtk.ActionGroup('BasicAction')
   30           # Agregamos la acción al grupo con un acelerador
   31           # None significa que se usa el acelerador del elemento de serie
   32           actiongroup.add_action_with_accel(action, None)
   33
   34           # Hacemos que la acción use el grupo de aceleradores
   35           action.set_accel_group(accelgroup)
   36
   37           # Creación de una barra de menú
   38           menubar = gtk.MenuBar()
   39           menubar.show()
   40           vbox.pack_start(menubar, False)
   41
   42           # Creación de la acción para Archivo y el elemento de menú
   43           file_action = gtk.Action('File', '_File', None, None)
   44           actiongroup.add_action(file_action)
   45           file_menuitem = file_action.create_menu_item()
   46           menubar.append(file_menuitem)
   47
   48           # Creación del menú de Archivo
   49           file_menu = gtk.Menu()
   50           file_menuitem.set_submenu(file_menu)
   51
   52           # Creación de un elemento delegado
   53           menuitem = action.create_menu_item()
   54           file_menu.append(menuitem)
   55
   56           # Creación de una barra de herramientas
   57           toolbar = gtk.Toolbar()
   58           toolbar.show()
   59           vbox.pack_start(toolbar, False)
   60
   61           # Creación de un elemento delegado de la barra de herramientas
   62           toolitem = action.create_tool_item()
   63           toolbar.insert(toolitem, 0)
   64
   65           # Creación y empaquetado de un control de Etiqueta
   66           label = gtk.Label('''
   67   Select File->Quit me! or
   68   click the toolbar Quit button or
   69   click the Quit button below or
   70   press Control+q
   71   to quit.
   72   ''')
   73           label.show()
   74           vbox.pack_start(label)
   75
   76           # Creación de un botón para usarlo como otro control delegado
   77           quitbutton = gtk.Button()
   78           # add it to the window
   79           vbox.pack_start(quitbutton, False)
   80
   81           # Conexión de la acción a su control delegado
   82           action.connect_proxy(quitbutton)
   83           # Se establece el texto de ayuda después de que se añade el elemento a la barra
   84           action.set_property('tooltip', action.get_property('tooltip'))
   85           tooltips = gtk.Tooltips()
   86           tooltips.set_tip(quitbutton, action.get_property('tooltip'))
   87
   88           window.show()
   89           return
   90
   91       def quit_cb(self, b):
   92           print 'Saliendo del programa'
   93           gtk.main_quit()
   94
   95   if __name__ == '__main__':
   96       ba = BasicAction()
   97       gtk.main()

Este ejemplo presenta un grupo de acciones ActionGroup como contenedor de las acciones Action que se usan en el programa. El apartado sobre grupos de acciones ActionGroups se adentrará en mayor detalle en su uso.

El código de las líneas 9-14 establece una ventana principal que contiene una VBox. Las líneas 16-35 establecen la acción Action "Quit" (salir) de la misma manera que en el programa de ejemplo simpleaction.py y la añaden con el acelerador de serie gtk.STOCK_QUIT (línea 32) al grupo de acción ActionGroup "BasicAction" (creado en la línea 29). Es de advertir el hecho de que, a diferencia del ejemplo simpleaction.py, aquí no es necesario llamar al método connect_accelerator() para la acción puesto que se hace de forma automática cuando se llama al método create_menu_item() en la línea 53.

Las líneas 38-40 crean una barra de menú (MenuBar) y la empaquetan en la VBox. Las líneas 43-44 crean una acción Action (file_action) para el menú File y la añaden al grupo actiongroup. Los elementos de menú File y Quit son creados en las líneas 45 y 53 y añadidos a la barra de menús (menubar) y al menú (file_menu) respectivamente en las líneas 46 y 54.

Igualmente se crea una barra de herramientas (Toolbar) que se añade a la VBox en las líneas 57-59. El elemento de la barra de herramientas ToolItem que actúa como delegado se crea y añade a la barra de herramientas en las líneas 62-63. Ha de advertirse que el texto de ayuda de la acción Action debe establecerse (línea 84) tras haber añadido el elemento de la barra de herramientas ToolItem a la propia barra de herramientas (Toolbar) para que pueda ser usado. De la misma manera, el texto de ayuda del botón Button debe añadirse de forma manual (líneas 84-86).

Figura 16.2, “Ejemplo Básico de Acción” muestra el programa de ejemplo basicaction.py en acción:

Figura 16.2. Ejemplo Básico de Acción

Ejemplo Básico de Acción

Es posible desconectar un control delegado (proxy) de una acción (Action) usando el método:

  action.disconnect_proxy(proxy)

16.1.1.4. Propiedades de Acción

Una acción Action tiene una serie de propiedades que controlan la representación y funcionamiento de sus controles delegados. Las más importantes entre ellas son las propiedades "sensitive" y "visible". La propiedad "sensitive" determina la sensibilidad de los controles delegados. Si "sensitive" es FALSE los controles delegados no pueden activarse y normalmente se representarán engrisecidos. De la misma manera, la propiedad "visible" determina si los controles delegados son o no visibles. Si la propiedad "visible" de una acción Action es FALSE entonces sus controles delegados permanecerán ocultos.

Como veremos en el siguiente apartado, la sesibilidad o visibilidad de una acción Action también está controlada por la sensibilidad o visibilidad del grupo de acciones ActionGroup al que pertenece. Por lo tanto, para que una acción Action sea visible o sensible tanto sus propiedades como las del grupo ActionGroup al que pertenece deben concordar. Para establecer la sensibilidad o visibilidad efectiva de una acción Action se deben usar los siguientes métodos:

  result = action.is_sensitive()

  result = action.is_visible()

El nombre asignado a una acción Action se almacena en su propiedad "name", que se establece en el momento en que se crea la acción Action. Se puede obtener dicho nombre usando el método:

  name = action.get_name()

Otras propiedades que controlan la visualización de los controles delegados de una acción Action son:

"hide-if-empty"

Si es TRUE, se ocultan los delegados de menú vacíos para esta acción.

"is-important"

Si es TRUE, los elementos de barra de herramientas ToolItem delegados para esta acción muestran su texto en el modo gtk.TOOLBAR_BOTH_HORIZ.

"visible-horizontal"

Si es TRUE, el elemento de barra de herramientas ToolItem es visible cuando la barra de herramientas tiene orientación horizontal.

"visible-vertical"

Si es TRUE, el elemento de la barra de herramientas ToolItem es visible cuando la barra de herramientas tiene orientación vertical.

Otras propiedades de interés son:

"label"

La etiqueta usada para los elementos de menú y botones que activan esta acción.

"short-label"

Una etiqueta más breve que puede usarse en botones de barras de herramientas y en botones.

"stock-id"

El Elemento de Serie utilizado para obtener el icono, etiqueta y acelerador que se usará en los controles que representen esta acción.

"tooltip"

Un texto de ayuda para esta acción.

Adviértase que el programa de ejemplo basicaction.py anula la etiqueta de gtk.STOCK_QUIT sustituyéndola por "_Quit me!" y fija la propiedad "short-label" a "_Quit". La etiqueta corta se usa para las etiquetas del botón de barra de herramientas ToolButton y para la del botón Button, pero se usa la etiqueta completa en el caso del elemento de menú MenuItem. También es de reseñar que no es posible establecer el texto de ayuda de un elemento ToolItem hasta que es añadido a su barra de herramientas (Toolbar).

16.1.1.5. Acciones y Aceleradores

Una acción Action tiene tres métodos usados para establecer un acelerador:

  action.set_accel_group(accel_group)

  action.set_accel_path(accel_path)

  action.connect_accelerator()

Éstos, además del método gtk.ActionGroup.add_action_with_accel(), deberían ser suficientes en los casos en los que se haya de establecer un acelerador.

Un grupo de aceleración AccelGroup debe estabecerse siempre para una acciónAction. El método set_accel_path() es llamado por el método gtk.ActionGroup.add_action_with_accel(). Si se usa set_accel_path() entonces el camino del acelerador debería utilizar el formato por defecto: "<Actions>/nombre_del_grupo_de_acciones/nombre_de_la_acción". Finalmente, el método connect_accelerator() es llamado para completar la configuración de un acelerador.

Nota

Una acción Action debe tener un grupo AccelGroup y un camino de acelerador asociado a él antes de la llamada a connect_accelerator().

Puesto que el método connect_accelerator() puede ser llamado varias veces (por ejemplo, una vez por cada control delegado), el número de llamadas es almacenado, de forma que se produzca un número igual de llamadas al método disconnect_accelerator() antes de que se elimine el acelerador.

Tal como se ilustró en los programas de ejemplo anteriores, un acelerador de una acción Action puede ser usado por todos los controles delegados. Una acción Action debería ser parte de un grupo ActionGroup para poder usar el camino de acelerador por defecto, que tiene el formato: "<Actions>/nombre_del_grupo_de_acciones/nombre_de_la_acción". La forma más sencilla de añadir un acelerador es usar el método gtk.ActionGroup.add_action_with_accel() y el siguiente método general:

  • Crear un grupo de aceleradores AccelGroup y añadirlo a la ventana principal.
  • Crear un nuevo grupo de acciones ActionGroup
  • Crear una acción Action que especifique un elemento de Serie con un acelerador.
  • Añadir la acción Action al grupo ActionGroup utilizando el método gtk.ActionGroup.add_action_with_accel() especificando None para usar el acelerador del elemento de Serieo una cadena de acelerador aceptable por la función gtk.accelerator_parse().
  • Establecer el grupo AccelGroup para la acción Action usando el método gtk.Action.set_accel_group().
  • Completar la configuración del acelerador usando el método gtk.Action.connect_accelerator().

Cualquier control delegado creado por o conectado a la acción Action elegida utilizará el acelerador así establecido.

16.1.1.6. Acciones Conmutables

Tal como se mencionó previamente, una acción ToggleAction es una subclase de Action que permite la conmutación entre dos estados. El constructor de una acción del tipo ToggleAction requiere los mismos parámetros que una del tipo Action:

  toggleaction = gtk.ToggleAction(name, label, tooltip, stock_id)

Además de los métodos de la clase Action, también dispone de los siguientes métodos propios de ToggleAction:

  toggleaction.set_active(is_active)
  is_active = toggleaction.get_active()

establecer u obtener el valor actual de toggleaction. is_active es un valor booleano.

Es posible conectarse a la señal "toggled" especificando una retrollamada con la signatura:

  def toggled_cb(toggleaction, user_data)

La señal "toggled" se emite cuando un elemento de acción ToggleAction cambia su estado.

Un control elemento de menú MenuItem delegado de una acción ToggleAction se mostrará por defecto como un elemento de menú con marca de verificación (CheckMenuItem). Para que un elemento delegado MenuItem se muestre como un elemento de menú del tipo exclusión (RadioMenuItem) se ha de establecer la propiedad "draw-as-radio" como TRUE usando el método:

  toggleaction.set_draw_as_radio(draw_as_radio)

Se puede usar el siguiente método para determinar si los elementos de menú MenuItem de una acción conmutable ToggleAction se mostrarán como elementos de menú del tipo exclusión RadioMenuItem:

  draw_as_radio = toggleaction.get_draw_as_radio()

16.1.1.7. Acciones con Exclusión

Una acción con exclusión RadioAction es una subclase de una acción conmutable ToggleAction que puede ser agrupada de manera que solamente una de las acciones RadioAction está activa al mismo tiempo. Los controles delegados correspondiente son RadioMenuItem y RadioToolButton para barras de menú y de herramientas, respectivamente.

El constructor de una acción RadioAction posee los mismos argumentos que una acción de la clase Action, con el añadido de un valor entero único que se usa para identificar la acción RadioAction dentro de un grupo:

  radioaction = gtk.RadioAction(name, label, tooltip, stock_id, value)

El grupo de una RadioAction se puede establecer con el método:

  radioaction.set_group(group)

donde group es otra acción del tipo RadioAction al que se debe agrupar radioaction. El grupo que contiene una acción RadioAction puede obtenerse con el método:

  group = radioaction.get_group()

que devuelve la lista de objetos RadioAction que incluye radioaction.

El valor del miembro actualmente activo del grupo puede obtenerse con el método:

  active_value = radioaction.get_current_value()

Se puede conectar una retrollamada a la señal "changed" para recibir notificación del momento en el que cambia el miembro activo del grupo de acciones RadioAction. Nótese que únicamente es necesario conectarse a uno de los objetos RadioAction para seguir los cambios. La signatura de la retrollamada es:

  def changed_cb(radioaction, current, user_data)

donde current es el elemento RadioAction actualmente activo en el grupo.

16.1.1.8. Un ejemplo de Acciones

El programa de ejemplo actions.py ilustra el uso de los objetos de acción (Action), acción conmutable (ToggleAction) y acción con exclusión (RadioAction). Figura 16.3, “Ejemplo de Acciones” muestra el programa de ejemplo en funcionamiento:

Figura 16.3. Ejemplo de Acciones

Ejemplo de Acciones

Este ejemplo es suficientemente parecido a basicaction.py como para que no sea precisa una descripción detallada del mismo.

16.1.2. Grupos de Acciones (ActionGroups)

Tal como se mencionó en el apartado anterior, los objetos Action relacionados deberían añadirse a un grupo ActionGroup de manera que se disponga de un control conjunto sobre su visibilidad y sensibilidad. Por ejemplo, en una aplicación de procesamiento de textos, los elementos de menú y los botones de la barra de herramientas que especifican la justificación del texto podrían estar agrupados en un ActionGroup. Es de esperar que una interfaz de usuario tenga múltiples objetos ActionGroup que abarquen los diversos aspectos de la aplicación. Por ejemplo, las acciones globales tales como la creación de nuevos documentos, abrir y guardar un documento y salir de la aplicación probablemente formen un grupo ActionGroup, mientras que acciones tales como la modificación de la vista del documento formarían otro.

16.1.2.1. Creación de grupos de acciones (ActionGroups)

Un ActionGroup se crea mediante el constructor:

  actiongroup = gtk.ActionGroup(name)

donde name es un nombre único para el grupo ActionGroup. El nombre debería ser único puesto que se usa para construir el camino de acelerador por defecto de sus objetos Action.

El nombre de un ActionGroup puede obtenerse usando el método:

  name = actiongroup.get_name()

u obteniendo el contenido de la propiedad "name".

16.1.2.2. Adición de Acciones

Tal como se ilustra en el apartado Acciones, se puede añadir una acción Action existente a un grupo ActionGroup utilizando uno de los métodos siguientes:

  actiongroup.add_action(action)

  actiongroup.add_action_with_accel(action, accelerator)

donde action es la acción Action que se va a añadir y accelerator es una especificación de cadena de acelerador que resulte aceptable a la función gtk.accelerator_parse(). Si accelerator es None se usará el acelerador (si existe) asociado con la propiedad "stock-id" de action. Tal como se indicó anteriormente, el método add_action_wih_accel() es el preferible si se desea utilizar aceleradores.

El grupo ActionGroup ofrece tres métodos para hacer más sencilla la creación y adición de objetos de acción (Action) a un grupo de acción (ActionGroup):

  actiongroup.add_actions(entries, user_data=None)

  actiongroup.add_toggle_actions(entries, user_data=None)

  actiongroup.add_radio_actions(entries, value=0, on_change=None, user_data=None)

El parámetro entries es una secuencia de tuplas de entradas de acciones que aportan la información necesaria para crear las acciones que se añaden al grupo ActionGroup. El objeto RadioAction con el valor value se fija inicialmente como activo. on_change es una retrollamada que está conectada a la señal "changed" del primer objeto RadioAction del grupo. La signatura de on_changed es:

  def on_changed_cb(radioaction, current, user_data)

Las tuplas de entradas de objetos Action contienen:

  • El nombre de la acción. Debe especificarse.
  • Un identificador de elemento estándar (stock id) para la acción. Opcionalmente puede tener el valor por defecto None si se especifica una etiqueta.
  • La etiqueta para la acción. Opcionalmente puede tener el valor por defecto None si se ha especificado un identificador de elemento estándar (stock id).
  • El acelerador para la acción, en el formato comprensible para la función gtk.accelerator_parse(). Opcionalmente puede tener el valor por defecto de None.
  • El texto de ayuda de la acción. Opcionalmente puede tener el valor por defecto de None.
  • La función de retrollamada invocada cuando se activa la acción activated. Opcionalmente puede tener el valor por defecto None.

Como mínimo se debe especificar un valor para el campo name y un valor bien en el campo stock id o el campo label. Si se especifica una etiqueta entonces se puede indicar None como identificador de elemento estándar (stock id) si no se usa uno. Por ejemplo, la siguiente llamada al método:

  actiongroup.add_actions([('quit', gtk.STOCK_QUIT, '_Quit me!', None, 
                            'Quit the Program', quit_cb)])

añade una acción a actiongroup para salir del programa.

Las tuplas de entradas para los objetos ToggleAction son similares a las tuplas de entradas para objetos Action salvo que existe un campo optativo adicional flag que contiene un valor booleano que indica si la acción está activa. El valor por defecto del campo flag es FALSE. Por ejemplo, la siguiente llamada:

  actiongroup.add_toggle_actions([('mute, None, '_Mute', '<control>m', 
                                   'Mute the volume', mute_cb, True)])

añade un objeto ToggleAction al grupo actiongroup y lo configura inicialmente para que esté activo.

Las tuplas de entradas para objetos RadioAction son semejantes a las de los objetos Action pero incorporan un campo value en vez del campo callback:

  • El nombre de la acción. Debe ser especificado.
  • Un identificador de elemento estándar (stock id) para la acción. Opcionalmente puede tener el valor por defecto None si se especifica una etiqueta.
  • La etiqueta para la acción. Opcionalmente puede tener el valor por defecto None si se ha especificado un identificador de elemento estándar (stock id).
  • El acelerador para la acción, en el formato comprensible para la función gtk.accelerator_parse(). Opcionalmente puede tener el valor por defecto de None.
  • El texto de ayuda de la acción. Opcionalmente puede tener el valor por defecto de None.
  • El valor (value) que se debe tener el objeto de acción con exclusión. Opcionalmente tiene el valor por defecto de 0. Siempre se debería especificar en las aplicaciones.

Por ejemplo, el siguiente fragmento de código:

  radioactionlist = [('am', None, '_AM', '<control>a', 'AM Radio', 0)
                     ('fm', None, '_FM', '<control>f', 'FM Radio', 1)
                     ('ssb', None, '_SSB', '<control>s', 'SSB Radio', 2)]
  actiongroup.add_radio_actions(radioactionlist, 0, changed_cb)

crea tres objetos RadioAction y establece 'am' como la acción inicialmente activa y changed_cb como la retrollamada empleada cuando cualquiera de las acciones se active.

16.1.2.3. Obtención de iconos

Para obtener un objeto de acción (Action) de un grupo ActionGroup se utiliza el método:

  action = actiongroup.get_action(action_name)

Es posible otener una lista de objetos Action contenidos en un ActionGroup con el método:

  actionlist = actiongroup.list_actions()

16.1.2.4. Control de las Acciones

La sensibilidad y visibilidad de todos los objetos Action de un grupo de acciones ActionGroup puede controlarse estableciendo los valores de los atributos correspondientes. Los siguientes métodos facilitan la obtención y establecimiento de los valores de las propiedades:

  is_sensitive = actiongroup.get_sensitive()
  actiongroup.set_sensitive(sensitive)

  is_visible = actiongroup.get_visible()
  actiongroup.set_visible(visible)

Finally you can remove an Action from an ActionGroup using the method:

  actiongroup.remove_action(action)

16.1.2.5. Un ejemplo de grupo de acciones (ActionGroup)

El programa de ejemplo actiongroup.py reproduce la barra de menú y barra de herramientas del programa de ejemplo actions.py utilizando los métodos de ActionGroup. Además el programa incluye botones para controlar la sensibilidad y visibilidad de los elementos de menú y los elementos de la barra de herramientas. Figura 16.4, “Ejemplo de ActionGroup” muestra el programa el funcionamiento:

Figura 16.4. Ejemplo de ActionGroup

Ejemplo de ActionGroup

16.1.2.6. Señales de los grupos de acciones (ActionGroup)

Una aplicación puede rastrear la conexión y eliminación de controles delegados en objetos del tipo Action dentro de un grupo ActionGroup utilizando las señales "connect-proxy" y "diconnect-proxy". Las signaturas de las retrollamadas deben ser:

  def connect_proxy_cb(actiongroup, action, proxy, user_params)

  def disconnect_proxy_cb(actiongroup, action, proxy, user_params)

Esto permite que se puedan rastrear cambios que permiten hacer modificaciones adicionales al nuevo control delegado en el momento en que es conectado o para actualizar alguna otra parte de la interfaz de usuario cuando se desconecta uno de los controles delegados.

Las señales "pre-activate" y "post-activate" permiten a las aplicaciones hacer un proceso adicional inmediatamente antes o después de que se haya activado una acción. Las signaturas de las retrollamadas son:

  def pre_activate_cb(actiongroup, action, user_params)

  def post_activate_cb(actiongroup, action, user_params)

Estas señales son utilizadas fundamentalmente por la clase UIManager para proveer notificación global para todos los objetos Action en objetos ActionGroup utilizados por ella.