El diseño modelo/vista/controlador

Visión general

Tanto los widgets TreeView como los ComboBox se construyen sobre el diseño modelo/vista/controlador. El modelo (una implementación de Gtk.TreeModel, generalmente Gtk.TreeStore o Gtk.ListStore) almacena los datos; la vista (por ejemplo, Gtk.TreeView, Gtk.ComboBox, o Gtk.ComboBoxText) recibe las notificaciones de cambio y muestra el contenido del modelo. El controlador, finalmente, cambia el estado del modelo (a través de algunos métodos en la implementación del modelo, como append() o remove()) y le notifica a la vista de estos cambios (a través de señales como «changed»).

El modelo

La principal diferencia entre las dos implementaciones primarias de Gtk.TreeModel es que Gtk.ListStore contiene filas simples de datos sin hijos, mientras que Gtk.TreeStore también contiene filas de datos, pero cada fila puede tener filas hijas (que a su vez pueden tener filas hijas, y así sucesivamente).

Los datos en el modelo pueden obtenerse o modificarse usando el «iter» del árbol y el índice de columna, Gtk.TreeIter, o Gtk.TreePath.

Con el objeto de lista empotrado de Python puede usar len() para obtener el número de filas y usar fragmentos para obtener o establecer valores. De lo contrario, el método append() devuelve una instancia de Gtk.TreeIter, que apunta al lugar de la fila insertada recientemente. También puede obtener un Gtk.TreeIter llamando a get_iter().

Como Gtk.ListStore sólo contiene un nivel, es decir que los nodos no tienen nodos hijos, una ruta es esencialmente el índice de la fila a la que quiere acceder. En el caso de Gtk.TreeStore, una ruta es una lista de índices o una cadena. La forma de la cadena es una lista de números separados por «:». Cada número se refiere al desplazamiento en ese nivel. Entonces, la ruta «0» se refiere al nodo raíz y la ruta «2:4» al quinto hijo del tercer nodo.

Métodos útiles para un Gtk.TreeModel:

  • get_iter(ruta) devuelve una instancia de Gtk.TreeIter que apunta a ruta. Se espera que sea una lista de números separados por «:», o una tupla. Por ejemplo, la cadena «10:4:0» equivale a la tupla (10, 4, 0), ya que las dos crearían una ruta de profundidad 3 apuntando al 11º hijo del nodo raíz, el 5º hijo de ese 11º hijo, y el 1er hijo de ese 5º hijo.

  • iter_next(treeiter) devuelve una instancia de Gtk.TreeIter apuntando siguiendo el «treeiter» en el nivel actual o None si no hay un «iter» siguiente.

  • iter_has_child(treeiter) devuelve True si treeiter tiene hijos, False de lo contrario.

  • iter_children(treeiter) devuelve una instancia de Gtk.TreeIter apuntando al primer hijo de treeiter o None si treeiter no tiene hijos.

  • get_iter_first() devuelve una instancia de Gtk.TreeIter apuntando al primer iterador en el árbol (el que está en la ruta «0») o None si el árbol está vacío.

Métodos útiles para un Gtk.ListStore:

  • append(fila) añade una fila nueva a este «ListStore», donde fila puede ser una lista de valores para cada columna; row también puede omitirse o ser None, y en ese caso se añade una fila vacía. El método devuelve un Gtk.TreeIter apuntando a la fila añadida.

  • remove(iter) elimina iter del Gtk.ListStore, y devuelve True si el iter es válido, y False si no lo es. Después de eliminarse, iter se establece a la siguiente fila válida.

Métodos útiles para un Gtk.TreeStore:

  • append(padre, fila) añade una fila nueva a este «TreeStore»; padre debe ser un «Gtk.TreeIter» válido. Si «padre» no es None, entonces añadirá la fila nueva después del último hijo de «padre», de lo contrario añadirá una fila al nivel superior; fila puede ser una lista de valores para cada columna; o puede omitirse o ser None; en este último caso se añadirá una fila vacía. El método devuelve un Gtk.TreeIter apuntando a la fila añadida.

  • remove(iter) elimina iter del Gtk.ListStore, y devuelve True si el iter es válido, y False si no lo es. Después de eliminarse, iter se establece a la siguiente fila válida.

La vista: el caso de «TreeView»

Una vista de árbol muestra la estructura de elementos padres e hijos como un árbol. Consulte este ejemplo.

La Gtk.TreeViewColumn se usa para organizar las columnas verticales.

Métodos útiles para un Gtk.TreeView:

  • set_model(modelo) establece el modelo para esta vista de árbol. Si ya tiene un modelo, lo eliminará antes de establecer el nuevo. Si el modelo es None, entonces quitará el modelo viejo.

  • get_model() devuelve el modelo en el que está basada esta vista de árbol, None si no tiene modelo.

  • append_column(columna) añade la columna a la lista de columnas.

  • get_selection() obtiene la Gtk.TreeSelection asociada a esta vista de árbol.

Métodos útiles para un Gtk.TreeViewColumn:

  • add_attribute(renderizador, atributo, valor) añade un mapeo de atributo a esta columna. atributo es el parámetro en renderizador al que se le asigna el valor.

  • pack_start(renderizador, expandir) empaqueta el renderizador en el principio de esta columna. Si expandir es False, entonces no se le asigna a renderizador más espacio del que necesita. Cualquier espacio sin utilizar se divide equitativamente entre las celdas en las que «expandir» es True.

  • pack_end(renderizador, expandir) añade el renderizador al final de esta columna. Si expandir es False, entonces no se le asigna a renderizador más espacio del que necesita. Cualquier espacio sin utilizar se divide equitativamente entre celdas en las que expandir es True.

  • set_sort_column_id(id_columna_ordenada) establece la columna del modelo por la que debe ordenarse la vista. Esto también hace que se pueda pulsar la cabecera de la columna.

  • set_sort_indicator(opción) establece si se muestra una pequeña flecha en la cabecera de la columna; opción puede ser True (se muestra el indicador) o False.

  • set_sort_order(orden) cambia el orden por el que se ordena la columna; orden puede ser Gtk.SortType.ASCENDING o Gtk.SortType.DESCENDING.

La vista: el caso de la «ComboBox»

Una Gtk.ComboBox permite la selección de un elemento desde un menú desplegable, consulte este ejemplo. Para una lista de opciones textuales, también se puede usar Gtk.ComboBoxText, que es más simple. Tanto Gtk.ComboBox como Gtk.ComboBoxText pueden contener una entrada.

Métodos útiles para un Gtk.ComboBox:

  • El método estático new_with_entry() crea una Gtk.ComboBox nueva vacía con una entrada; el método estático new_with_model(modelo) crea una con el modelo inicializado a modelo nueva; y el método estático new_with_model_and_entry(modelo) es una combinación de los dos.

  • get_active_iter() devuelve un Gtk.TreeIter que apunta al elemento activo actual. Si no existe, devuelve None.

  • set_model(modelo) establece el modelo que esta caja combinada usa a modelo, y quita un modelo anterior (si existiera). Si modelo es None, entonces lo quitará. Tenga en cuenta que esta función no limpia los renderizadores de celda.

  • set_entry_text_column(columna_texto) establece la columna del modelo de la que esta caja combinada obtendrá las cadenas a columna_texto. La columna columna_texto en el modelo de esta caja combinada debe ser del tipo str (esto sólo es relevante si esta caja combinada se creó con la propiedad «has-entry» establecida a «True»).

  • set_wrap_width(anchura) establece la anchura del ajuste de línea de esta caja combinada a anchura. La anchura de ajuste de línea es básicamente el número preferido de columnas en el que quiere que el diálogo emergente se distribuya en una rejilla.

Métodos útiles para un Gtk.ComboBoxText:

  • El método estático new_with_entry() crea una Gtk.ComboBoxText nueva vacía con una entrada.

  • append_text(texto) añade texto a la lista de cadenas almacenadas en esta caja combinada.

  • get_active_text() devuelve la cadena actualmente activa en esta caja combinada, o None si no hay ninguna seleccionada. Si esta caja combinada contiene una entrada, esta función devolverá su contenido (que no será necesariamente un elemento de la lista).

La vista: los «CellRenderer»

La vista hace uso de Gtk.CellRenderer de varios tipos para dibujar los datos.

Implementaciones de Gtk.CellRenderer y métodos útiles:

  • Gtk.CellRendererText: muestra texto en una celda

  • Gtk.CellRendererToggle: muestra un interruptor o botón de radio en una celda. Métodos útiles:

    • set_active(opción): activa o desactiva un renderizador de celda

    • get_active(): devuelve si el renderizador de celda está activado

    • set_radio(radio): si «radio» es True, el renderizador de celda muestra un interruptor de radio (es decir, un interruptor en un grupo mutuamente exclusivo); si es False, muestra una casilla de verificación (una opción booleana independiente)

    • get_radio(): devuelve si se están mostrando botones de radio en lugar de casillas de verificación.

  • Gtk.CellRendererPixbuf: muestra una imagen en una celda

  • Gtk.CellRendererCombo: muestra texto en una celda; pero mientras que Gtk.CellRendererText ofrece una entrada simple para editar el texto, Gtk.CellRendererCombo ofrece un widget Gtk.ComboBox para editarlo. Puede usarse con o sin un widget «Gtk.Entry» asociado, dependiendo del valor de la propiedad «has-entry».

  • Gtk.CellRendererProgress: muestra un valor numérico en forma de barra de progreso en una celda; puede mostrar un texto sobre ella

  • Gtk.CellRendererSpinner: muestra una animación giratoria en una celda

  • Gtk.CellRendererSpin: muestra un botón incremental en una celda

  • Gtk.CellRendererAccel: muestra un acelerador de teclado en una celda

El controlador: la selección

La mayoría de las aplicaciones no solo necesitarán mostrar datos, sino también recibir eventos de entrada de los usuarios. Para hacer esto, simplemente obtenga una referencia a un objeto de selección y conéctela a la señal «changed».

select = tree.get_selection()
select.connect("changed", on_tree_selection_changed)

Después, para obtener datos de la fila seleccionada:

def on_tree_selection_changed(selection):
    model, treeiter = selection.get_selected()
    if treeiter != None:
        print "You selected", model[treeiter][0]

Métodos útiles para un Gtk.TreeSelection:

  • set_mode(tipo) establece el tipo de la selección, donde «tipo» puede ser

    • Gtk.SelectionMode.NONE: la selección no es posible

    • Gtk.SelectionMode.SINGLE: se puede seleccionar uno o ningún elemento

    • Gtk.SelectionMode.BROWSE: se selecciona exactamente un elemento. En algunas circunstancias, como inicialmente o durante una operación de búsqueda, es posible que ningún elemento esté seleccionado. Lo que realmente se prohíbe es que el usuario deseleccione un elemento actualmente seleccionado excepto si selecciona otro.

    • Gtk.SelectionMode.MULTIPLE: se puede seleccionar cualquier número de elementos. Las pulsaciones cambien el estado de un elemento. Se puede usar la tecla «Ctrl» para agrandar la selección, y «Mayús» para seleccionar entre el foco y el hijo al que apunta. Algunos widgets también pueden permitir arrastrar y soltar para seleccionar un rango de elementos.

  • get_selected() devuelve una tupla (modelo, treeiter), donde modelo es el modelo actual y treeiter un Gtk.TreeIter que apunta a la fila actualmente seleccionada, o «None» si no la hay. El método no funciona si el modo de selección es Gtk.SelectionMode.MULTIPLE; en ese caso, use get_selected_rows() en su lugar, que devuelve una lista de instancias Gtk.TreePath de todas las filas seleccionadas.