El control ComboBox sustituye el obsoleto
OptionMenu con
un control potente que utiliza un TreeModel (generalmente un
ListStore) que proporciona los elementos de la lista que se mostrarán.
El ComboBox implementa la interfaz
CellLayout, que proporcina diversos métodos para gestionar la
visualización de los elementos de la lista. Uno o más
methods for managing the display of the list items. One or more
CellRenderers se pueden empaquetar en un
ComboBox para personalizar la visualización de los elementos de
la lista.
La forma sencilla de crear y poblar un
ComboBox es utilizar la función auxiliar:
combobox = gtk.combo_box_new_text()
Esta función crea una ComboBox y su almacén
ListStore asociado y lo empaqueta con un
CellRendererText. Los siguientes métodos auxiliares se usan
para poblar o eliminar los contenidos de la ComboBox y su
ListStore:
combobox.append_text(text) combobox.append_text(text) combobox.insert_text(position,text) combobox.remove_text(position)
donde text es la cadena que se añadirá a la
ComboBox y position es el índice donde
se insertará o eliminará el texto text. En la mayoría de los casos
las funciones y métodos auxiliares es todo lo que se necesitará.
El programa de ejemplo comboboxbasic.py demuestra el uso de las anteriores funciones y métodos. Figura 16.5, “ComboBox Básica” ilustra el programa en ejecución:
Para obtener el texto activo se puede usar el método:
texto = combobox.get_active_text()
Sin embargo, hasta la versión 2.6 no se proporciona en
GTK+ un método cómodo para obtener el texto activo.
Para ello se podría usar una implementación similar a:
def get_active_text(combobox):
model = combobox.get_model()
active = combobox.get_active()
if active < 0:
return None
return model[active][0]
El índice del elemento activo se obtiene a través del método:
active = combobox.get_active()
El elemento activo se puede establecer con el método:
combobox.set_active(index)
donde index es un entero mayor que
-2. Si index es -1 no hay elemento activo y el control
ComboBox estará en blanco. Si index es
menor que -1, la llamada será ignorada. Si index es mayor que -1
el elemento de la lista con dicho índice será mostrado.
Se puede conectar a la señal "changed" de un
ComboBox para recibir notificación del cambio del elemento activo.
La signatura del manejador de "changed" es:
def changed_cb(combobox, ...):
donde ... representa cero o más argumentos pasados al
método GObject.connect().
La creación de una lista ComboBox mediante la función
gtk.combo_box_new_text() es aproximadamente equivalente al
siguiente código:
liststore = gtk.ListStore(str) combobox = gtk.ComboBox(liststore) cell = gtk.CellRendererText() combobox.pack_start(cell, True) combobox.add_attribute(cell, 'text', 0)
Para sacar partido de la potencia de las variadas clases de objetos
TreeModel y CellRenderer
es necesario construir una ComboBox utilizando el constructor:
combobox = gtk.ComboBox(model=None)
donde model es un modelo
TreeModel. Si se crea una lista
ComboBox sin asociarle un
TreeModel es posible añadirlo a posteriori utilizando el método:
combobox.set_model(model)
Se puede obtener el TreeModel asociado con el
método:
model = combobox.get_model()
Algunas de las cosas que se pueden hacer con una
ComboBox son:
TreeModel con otras
ComboBoxes y
TreeViews.ComboBox.TreeStore o
ListStore existente como modelo para los elementos de la lista de la
ComboBox.TreeModelSort para disponer de una
lista de ComboBox ordenada.TreeModelFilter para usar un subárbol
de un TreeStore como fuente de elementos de la lista de la
ComboBox.TreeModelFilter para utilizar un subconjunto
de las filas de un TreeStore o
ListStore como elementos de la lista de la
ComboBox.El uso de los objetos TreeModel y
CellRenderer se detalla en el capítulo de Controles de Vista de Árbol.
Los elementos de la lista de la ComboBox se pueden
mostrar en una tabla si se tiene un gran número de elementos que visualizar. En otro caso,
la lista tendrá flechas de desplazamiento si la lista no puede ser mostrada en su totalidad. El
siguiente método se usa para determinar el número de columnas que se mostrarán:
combobox.set_wrap_width(width)
donde width es el número de columnas de la tabla que
muestra los elementos de la lista. Por ejemplo, el programa comboboxwrap.py muestra una lista de 50 elementos
en 5 columnas. Figura 16.6, “ComboBox con una Disposición Asociada”
ilustra el programa en acción:
Con un gran número de elementos, digamos, por ejemplo, 50, el uso del método
set_wrap_width() tendrá un mal rendimiento debido al cálculo
de la disposición en tabla. Para tener una noción del efecto se puede modificar el programa
comboboxwrap.py
en su línea 18 de forma que muestre 150 elementos.
for n in range(150):
Ejecute el programa para obtener una idea aproximada del tiempo de inicialización. Luego modifíquelo comentando la línea 17:
#combobox.set_wrap_width(5)
Ejecute y cronometre de nuevo. Debería ejecutarse significativamente más rápido. Unas 20 veces más rápido.
Además del método get_active() antes descrito, se
puede obtener un iterador TreeIter que señala la fila activa mediante
el método:
iter = combobox.get_active_iter()
También se puede establecer el elemento de la lista activa usando un iterador
TreeIter con el método:
combobox.set_active_iter(iter)
Los métodos set_row_span_column() y
set_column_span_column() permiten la especificación de un
número de columna de un TreeModel que contiene el número de filas
o columnas que debe abarcar el elemento de la lista en una disposición de tabla. Desgraciadamente, en GTK+ 2.4 estos métodos funcionan mal.
Puesto que ComboBox implementa la interfaz
CellLayout, que tiene capacidades similares a las de una
TreeViewColumn (véase la sección de TreeViewColumn para más información).
En resumen, la interfaz proporciona:
combobox.pack_start(cell,expand=True) combobox.pack_end(cell,expand=True) combobox.clear()
Los dos primeros métodos empaquetan un CellRenderer
en la ComboBox y el método clear()
elimina todos los atributos de todos los CellRenderers.
Los siguientes métodos:
comboboxentry.add_attribute(cell,attribute,column) comboboxentry.set_attributes(cell,...)
establecen los atributos del CellRenderer indicado
por cell. El método add_attribute()
toma una cadena de nombre de atributo attribute (p.e. 'text') y un
número entero de columna column de la columna en el
TreeModel usado, para fijar el atributo
attribute. Los argumentos restante del método
set_attributes() son pares
atributo=columna (p.e. text=1).
El control ComboBoxEntry sustituye al control
Combo. Es una subclase del control
ComboBox y contiene un control hijo de entrada
Entry que obtiene sus contenidos seleccionando un elemento
en la lista desplegable o introduciendo texto directamente en la entrada bien desde el teclado
o pegándolo desde un portapapeles Clipboard o una selección.
Como la ComboBox, la
ComboBoxEntry se puede crear con la función auxiliar:
comboboxentry = gtk.combo_box_entry_new_entry()
Una ComboBoxEntry se debe rellenar utilizando los
métodos auxiliares de ComboBox descritos en
Uso Básico de ComboBox.
Puesto que un control ComboBoxEntry es un control
Bin, su control hijo de entrada Entry
está disponible utilizando el atributo "child" o el método
get_child():
entry = comboboxentry.child entry = comboboxentry.get_child()
Se puede obtener el texto de la entrada Entry utilizando su
método get_text().
Al igual que ComboBox, es posible seguir los cambios del
elemento activo de la lista conectándose a la señal "changed". Desgraciadamente, esto no
permite seguir los cambios en la entrada Entry que se hacen por
entrada directa. Cuando se hace una entrada directa al control Entry
se emite la señal "changed", pero el índice devuelto por el método
get_active() será -1. Para seguir todos los cambios del texto
de la entrada Entry text, será necesario utilizar la señal "changed"
de la entrada Entry. Por ejemplo:
def changed_cb(entry):
print entry.get_text()
comboboxentry.child.connect('changed', changed_cb)
imprimirá el texto tras cada cambio en el control hijo
Entry. Por ejemplo, el programa comboboxentrybasic.py muestra el uso
de la API auxiliar. Figura 16.7, “ComboBoxEntry Básica” ilustra la ejecución del programa:
Obsérvese que cuando se modifica el texto de la entrada
Entry debido a la selección de un elemento de la lista desplegable
se llama dos veces al manejador de la señal "changed": una vez cuando se elimina el texto, y,
otra cuando el texto se establece desde el elemento seleccionado de la lista.
El constructor de una ComboBoxEntry es:
comboboxentry = gtk.ComboBoxEntry(model=None,column=-1)
donde model es un
TreeModel y column es el número de la
columna en el modelo model que se usará para fijar los elementos de
la lista. Si no se indica la columna el valor predeterminado es -1 que significa que el texto de la
columna no está especificado.
La creación de una ComboBoxEntry utilizando la función
auxiliar gtk.combo_box_entry_new_text() es equivalente al siguiente
código:
liststore = gtk.ListStore(str) comboboxentry = gtk.ComboBoxEntry(liststore, 0)
La ComboBoxEntry añade un par de métodos que se usan
para establecer y recuperar el número de columna del TreeModel
que se usará para fijar las cadenas de los elementos de la lista:
comboboxentry.set_text_column(text_column)
text_column = comboboxentry.get_text_column()
La columna de texto también se puede obtener y especificar utilizando la propiedad
"text-column". Véase la Sección de Uso Avanzado de ComboBox para más
información sobre el uso avanzado de una ComboBoxEntry.
La aplicación debe establecer la columna de texto para que la
ComboBoxEntry fije los contenidos de la entrada
Entry desde la lista desplegable. La columna de texto únicamente
puede determinarse una vez, bien utilizando el constructor o utilizando el método
set_text_column().
Al crear una ComboBoxEntry ésta se empaqueta con un
nuevo CellRendererText que no es accesible. El atributo
'text' del CellRendererText se establece como un efecto colateral
de la determinación de la columna de texto utilizando el método
set_text_column(). Se pueden empaquetar CellRenderers adicionales en una
ComboBoxEntry para la visualización en la lista desplegable. Véase
la Sección de Uso Avanzado de ComboBox
para más información.