Crear  Editar  FrontPage  Indexes  Buscar  Cambios  History  RSS  Login

tut-treeview-selection-handle

Trabajando con selecciones

Una de las funciones básicas de un árbol o una lista es poder seleccionar/deseleccionar las filas. Las selecciones se manejan con el objeto Gtk::TreeView#selection. Cada TreeView contiene de forma automática un Gtk::TreeSelection asociado a él, y se puede obtener usando el método Gtk::TreeView#selection. Las selecciones se controlan por completo del lado del TreeView, lo cual significa que el modelo no sabe si una fila está seleccionada o no. No hay una razón en particular para que el control de las selecciones no se haya implementado con métodos accesibles desde el propio widget TreeView, pero por razones de limpieza de la API y claridad del código los desarrolladores de Gtk+ decidieron crear el objeto Gtk::TreeSelection que se comunica de forma interna con el widget TreeView.

Hay tres formas de trabajar con selecciones: se puede obtener una lista de las filas actualmente seleccionadas cuando sea necesatio, por ejemplo en un método que llama a un menú contextual, o se pueden controlar todas las acciones de seleccion y deseleccion y mantener una lista de las filas seleccionadas para cuando se necesite; como último recurso, se puede atravesar la lista o árbol y comprobar cada una de las filas para ver si está seleccionada o no (necesario, por ejemplo, si se necesitan todas las filas que no están seleccionadas).

Modos de selección

Se puede usar Gtk::TreeSelection#mode= para indicar el modo en que se manejan las selecciones. Hay cuatro modos de selección:

Obteniendo las filas seleccionadas

Se puede acceder a las filas seleccionadas recorriéndolas con Gtk::TreeSelection#selection_each.

Si se está usando como modo de selección Gtk::SELECTION_SINGLE o Gtk::SELECTION_BROWSE, la mejor forma de obtener la fila seleccionada es el método Gtk::TreeSelection#selected, que devuelve un Gtk::TreeIter que apunta a la fila seleccionada (si hay alguna fila seleccionada), o nil en caso contrario. Se usa de la siguiente forma:

selection = view.selection

if iter = selection.selected
  puts "la fila seleccionada es #{iter[0]}"
else
  puts "fila no seleccionada"
end

Hay algo a tener en cuenta a la hora de elminiar filas del modelo con el método Gtk::TreeSelection#selected_each method. La forma más fácil de eliminar varias filas de una vez ya se ha comentado en un artículo anterior, p.e. se obtienen las referencias de fila de todas las filas seleccionadas y se eliminan una a una. En ningún caso se pueden eliminar filas desde el bloque, símplemente no está permitido.

Aquí se muestra un ejemplo sobre el uso de Gtk::TreeSelection#selected_each:

selection.selected_each do |model, path, iter|
  puts "#{iter[0]} está seleccionada"
end

Usando funciones de selección

Se puede configurar una función de selección personalizada con Gtk::TreeSelection#set_selection_function. Este bloque de código será llamado cada vez que una fila se seleccionada o deseleccionada (concretamente: se le llama antes de que el estado de selección de la fila cambie). Las funciones de selección se usan generalmente en los siguientes casos:

  • Mantener una lista de los elementos seleccionados (el programador mantiene por si mismo la lista de elementos seleccionados). En este caso, notese de nuevo que el bloque de código es llamado antes de que cambie el estado de cada fila. En otras palabras: si la fila va a ser seleccionada, entonces el argumento boolean path_currently_selected que se pasa sigue siendo FALSE. Hay que tener en cuenta también que no se le llama siempre cuando una fila es eliminada, de modo que se debe deseleccionar una fila antes de eliminarla para asegurarse de que se llama a la función de selección y elimine la fila de nuestra lista, o comprobar la valided de una fila cuando procesamos la lista de selección que estamos manteniendo. No se deben almacenar TreePaths en la lista autogestionada de filas seleccionadas, ya que al eliminar o añadir filas el modelo se regenera y el TreePath puede apuntar a otra fila. En su lugar, se usan TreeRowReference u otras técnicas únicas para identificar una fila.
  • Indicar a Gtk+ cuando está permitido seleccionar o deseleccionar una fila específica (el programador debe asegurarse de que sea obvio para el usuario cuando una fila es seleccionable o no, de lo contrario creará confusión cuando dicho usuario símplemente no pueda seleccionar o deseleccionar una fila). Esto se consigue devolviendo TRUE o FALSE.
  • Tomando medidias adicionales cuando se selecciona/deselecciona una fila.

Veamos otro ejemplo:

selection.set_select_function do |selection, model, path, currently_selected|
  if iter = model.get_iter(path)
    if ! currently_selected
      puts "#{iter[0]} va a ser seleccionada"
        else
      puts "#{iter[0]} va a se deseleccionada"
    end
  end

  # permite que cambie el estado de selección
  true
end

Comprobando si una fila está seleccionada

Se puede comprobar si una fila está seleccionada con los métodos Gtk::TreeSelection#iter_is_selected? y Gtk::TreeSelection#path_is_selected?. Si se necesita disponer de todas las filas que no están seleccionadas, por ejemplo, se puede recorrer la lista o árbol completo, y usar los métodos anteriores para comprobar cada una de las filas.

Obteniendo el número de filas seleccionadas

En ocasiones es se necesita saber el número de filas que se encuentran seleccionadas (por ejemplo para activar o desactivar entradas de un menú contextual antes de abrirlo). Si se están usando los modos de selección Gtk::SELECTION_SINGLE o Gtk::SELECTION_BROWSE, resulta trivial comprobarlo con Gtk::TreeSelection#selected, que devolverá un Gtk::TreeIter si alguna fila está seleccionada o nil en caso contrario. Obviamente, si se está usando Gtk::SELECTION_NONE el número de filas seleccionadas será siempre 0.

En el caso de Gtk::SELECTION_MULTIPLE o como aproximación general para todos los modos de selección, aquí se muestra un método sencillo que usa Gtk::TreeSelection#selected_each:

def count_selected_rows(selection)
  count = 0
  selection.selected_each { count += 1 }
  count
end
Ultimas actualizaciones:2011/06/07 12:35:59
Clave:
Referencias:[tut-treeview]