Capítulo 14. Control de Vista de Árbol (TreeView)

Tabla de contenidos

14.1. Introducción
14.2. La Interfaz y Almacén de Datos TreeModel
14.2.1. Introducción
14.2.2. Creación de Objetos TreeStore (árbol) y ListStore (lista)
14.2.3. Cómo referirse a las filas de un modelo TreeModel
14.2.4. Adición de filas
14.2.5. Eliminación de Filas
14.2.6. Gestión de los datos de las filas
14.2.7. Soporte del protocolo de Python
14.2.8. Señales de TreeModel
14.2.9. Ordenación de filas de modelos TreeModel
14.3. TreeViews (Vistas de árbol)
14.3.1. Creación de un TreeView (vista de árbol)
14.3.2. Obtención y establecimiento del Modelo de un TreeView
14.3.3. Definición de las propiedades de un TreeView
14.4. Visualizadores de Celda (CellRenderer)
14.4.1. Introducción
14.4.2. Tipos de Visualizadores CellRenderer
14.4.3. Propiedade de un CellRenderer
14.4.4. Atributos de un CellRenderer
14.4.5. Función de Datos de Celda
14.4.6. Etiquetas de Marcado en CellRendererText
14.4.7. Celdas de Texto Editables
14.4.8. Celdas Biestado Activables
14.4.9. Programa de Ejemplo de Celda Editable and Activable
14.5. TreeViewColumns (columnas de vista de árbol)
14.5.1. Creación de TreeViewColumns (columnas de vista de árbol)
14.5.2. Gestión de los CellRenderers (Intérpretes de celda)
14.6. Manipulación de TreeViews
14.6.1. Gestión de las Columnas
14.6.2. Expansión y Contracción de Filas Hijas
14.7. Señales de TreeView
14.8. Selecciones TreeSelections
14.8.1. Obtención de TreeSelection
14.8.2. Modos de una selección TreeSelection
14.8.3. Obtención de la Selección
14.8.4. Uso de una Función de TreeSelection
14.8.5. Selección y Deselección de Filas
14.9. Arrastrar y Soltar en TreeView
14.9.1. Reordenación mediante Arrastrar y Soltar
14.9.2. Arrastar y Soltar Externo
14.9.3. Ejemplo de Arrastrar y Soltar en TreeView
14.10. TreeModelSort y TreeModelFilter
14.10.1. TreeModelSort (Modelo de Árbol Ordenado)
14.10.2. TreeModelFilter (Modelo de árbol filtrado)
14.11. El Modelo de Árbol Genérico (GenericTreeModel)
14.11.1. Visión general de GenericTreeMode
14.11.2. La Interfaz GenericTreeModel
14.11.3. Adición y Eliminación de Filas
14.11.4. Gestión de Memoria
14.11.5. Otras Interfaces
14.11.6. Utilización de GenericTreeModel
14.12. El Visualizador de Celda Genérico (GenericCellRenderer)

El control TreeView (control de vista de árbol) muestra listas y árboles de múltiples columnas. Sustituye los antiguos controles List, CList, Tree y CTree por un conjunto de objetos mucho más potente y flexible que utilizan el patrón Modelo-Vista-Controlador (MVC) para proporcionar las siguientes funcionalidades:

Obviamente, todas estas posibilidades conllevan el coste de un conjunto de objetos e interfaces significativamente más complejo y que puede llegar a parecer intimidatorio inicialmente. En el resto del capítulo exploraremos los objetos e interfaces de la vista de árbol (TreeView) para comprender sus usos habituales. Los usos más esotéricos tendrán que ser investigados por el lector.

Comenzaremos con una rápida visión general de objetos e interfaces para posteriormente bucear en la interfaz de TreeModel y en las clases predefinidas ListStore y TreeStore.

14.1. Introducción

El control TreeView (vista de árbol) es el objeto de interfaz de usuario que muestra los datos almacenados en un objeto que implemente la interfaz TreeModel. En PyGTK 2.0 se proporcionan dos clases base para modelos de árbol.:

  • TreeStore (almacén de datos en árbol), que proporcionan almacenamiento para datos jerárquicos, organizándolos como filas de un árbol y con los datos en columnas. Cada fila del árbol puede tener cero o más filas hijas, aunque todas las filas deben tener el mismo número de columnas.
  • ListStore (almacén de datos en lista), que proporciona almacenamiento para datos tabulares, con una organización en filas y columnas, de una manera similar a la tabla de una base de datos relacional. Un ListStore (almacén de datos en lista) realmente consiste en una versión simplificada de un TreeStore (almacén de datos en árbol), cuyas filas no tienen descendientes. Fue creada para proporcionar una interfaz más sencilla (y presuntamente más eficiente) a un modelo de datos tan común. Y,

estos dos modelos adicionales se superponen (o se interponen) a los modelos base:

  • TreeModelSort, que proporciona un modelo en el que los datos del modelo de árbol subyacente se mantienen ordenados. Y,
  • TreeModelFilter, que proporciona un modelo que contiene un subconjunto de los datos del modelo subyacente. Este modelo únicamente está disponible desde la versión de PyGTK 2.4 y posteriores.

Un TreeView (vista de árbol) muestra todas las filas que contiene un TreeModel, pero permite mostrar selectivamente algunas de las columnas. También es posible presentar las columnas en un orden diferente al de almacenamiento en el TreeModel.

Un TreeView usa objetos del tipo TreeViewColumn (columnas de vista de árbol) para organizar la visualización de los datos en columnas. Cada TreeViewColumn muestra una columna con un encabezado opcional que puede contener los datos de diversas columnas de un TreeModel. Los objetos TreeViewColumn se empaquetan (de forma semejante a los contenedores HBox) con objetos CellRenderer (intérpretes de celda), para generar la visualización de los datos asociados situados en una fila y columna de un TreeModel. Existen tres clases de CellRenderer predefinidas:

  • CellRendererPixbuf, que muestra una imagen del tipo pixbuf en las celdas de un TreeViewColumn.
  • CellRendererText, que muestra una cadena en las celdas de un TreeViewColumn. Si es necesario convierte los datos de la columna a cadenas de texto. Por ejemplo, si se mostrase una columna de datos consistente en números en coma flotante, el CellRendererText los convertiría en cadenas de texto antes de mostrarlos.
  • CellRendererToggle, que muestra un valor booleano como un botón conmutable en las celdas de un TreeViewColumn.

Una TreeViewColumn puede contener varios objetos CellRenderer para proporcionar una columna que, por ejemplo, pueda contener una imagen y un texto juntos.

Finalmente, los objetos TreeIter (iterador de árbol), TreeRowReference (referencia de fila de árbol) y TreeSelection (selección de árbol) proporcionan un puntero transitorio a la fila de un TreeModel, un puntero persistente a la fila de un TreeModel y un objeto que gestiona una selección en una TreeView.

La visualización de un TreeView se compone de las siguientes operaciones generales (aunque no necesariamente en este orden):

  • Se crea un objeto de modelo de árbol (TreeModel), generalmente un ListStore o un TreeStore con una o más columnas de un tipo de datos determinado.
  • El modelo de árbol puede entonces llenarse con una o más filas de datos.
  • Se crea un control TreeView y se asocia al modelo de árbol.
  • Se crean una o más columnas TreeViewColumn y se insertan en el TreeView. Cada una de ellas resultará en la visualización de una columna.
  • Para cada TreeViewColumn se crea uno o más intérpretes de celda CellRenderer, que son añadidos a cada TreeViewColumn.
  • Se fijan los atributos de cada CellRenderer para indicar de qué columnas del modelo de árbol han de tomar los datos del atributo, como por ejemplo, el texto que se ha de mostrar. Esto permite que los CellRenderer muestren las columnas de cada fila de forma distinta.
  • El TreeView se inserta y es mostrado en una ventana (Window) o una ventana con barras de desplazamiento (ScrolledWindow).
  • Los datos del modelo de árbol se manipulan programáticamente en respuesta a las acciones de los usuarios y usuarias. El TreeView rastreará de forma automática los cambios.

El programa de ejemplo basictreeview.py ilustra la creación y visualización de un objeto sencillo TreeView:

    1   #!/usr/bin/env python
    2
    3   # example basictreeview.py
    4
    5   import pygtk
    6   pygtk.require('2.0')
    7   import gtk
    8
    9   class BasicTreeViewExample:
   10
   11       # close the window and quit
   12       def delete_event(self, widget, event, data=None):
   13           gtk.main_quit()
   14           return gtk.FALSE
   15
   16       def __init__(self):
   17           # Create a new window
   18           self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
   19
   20           self.window.set_title("Basic TreeView Example")
   21
   22           self.window.set_size_request(200, 200)
   23
   24           self.window.connect("delete_event", self.delete_event)
   25
   26           # create a TreeStore with one string column to use as the model
   27           self.treestore = gtk.TreeStore(str)
   28
   29           # we'll add some data now - 4 rows with 3 child rows each
   30           for parent in range(4):
   31               piter = self.treestore.append(None, ['parent %i' % parent])
   32               for child in range(3):
   33                   self.treestore.append(piter, ['child %i of parent %i' %
   34                                                 (child, parent)])
   35
   36           # create the TreeView using treestore
   37           self.treeview = gtk.TreeView(self.treestore)
   38
   39           # create the TreeViewColumn to display the data
   40           self.tvcolumn = gtk.TreeViewColumn('Column 0')
   41
   42           # add tvcolumn to treeview
   43           self.treeview.append_column(self.tvcolumn)
   44
   45           # create a CellRendererText to render the data
   46           self.cell = gtk.CellRendererText()
   47
   48           # add the cell to the tvcolumn and allow it to expand
   49           self.tvcolumn.pack_start(self.cell, True)
   50
   51           # set the cell "text" attribute to column 0 - retrieve text
   52           # from that column in treestore
   53           self.tvcolumn.add_attribute(self.cell, 'text', 0)
   54
   55           # make it searchable
   56           self.treeview.set_search_column(0)
   57
   58           # Allow sorting on the column
   59           self.tvcolumn.set_sort_column_id(0)
   60
   61           # Allow drag and drop reordering of rows
   62           self.treeview.set_reorderable(True)
   63
   64           self.window.add(self.treeview)
   65
   66           self.window.show_all()
   67
   68   def main():
   69       gtk.main()
   70
   71   if __name__ == "__main__":
   72       tvexample = BasicTreeViewExample()
   73       main()

En programas reales el TreeStore probablemente se llenaría de datos después de que la visualización del TreeView se produjese por una acción del usuario. Nos detendremos en los detalles de las interfaces de TreeView en secciones posteriores. Figura 14.1, “Programa elemental de ejemplo de TreeView” muestra la ventana creada por el programa basictreeview.py tras la expanxión de un par de filas madre.

Figura 14.1. Programa elemental de ejemplo de TreeView

Programa elemental de ejemplo de TreeView

Ahora examinemos la interfaz de TreeModel y los modelos que la implementan.