10 septiembre 2007

El componente TTreeView (I)

Cuando queremos representar una información en forma de árbol incluyendo nodos padres e hijos el componente ideal para ello es el TreeView, el cual funciona exactamente igual que la parte izquierda del Explorador de Windows.

Veamos las peculiaridades que aporta este componente. Todas las funciones las voy a aplicar sobre esta pantalla:


AÑADIENDO ELEMENTOS AL ARBOL

Cuando se añaden elementos a un árbol pueden pertenecer al elemento raiz del mismo (sin padre) o pertenecer a un elemento ya creado. Los elementos del árbol se llaman nodos (Node) pudiendose crear tantos niveles de nodos como se deseen.

Vamos a crear un procedimiento asociado al botón Nuevo que va a añadir un nuevo nodo al árbol. El elemento insertado será un nodo raiz, a menos que el usuario seleccione un nodo antes de ello, que hará que sea su hijo:

procedure TFTreeView.BNuevoClick( Sender: TObject );
var
sNombre: string;
begin
sNombre := InputBox( 'Crear un nodo', 'Nombre:', '' );

if sNombre <> '' then
begin
// ¿Hay un nodo seleccionado?
if TreeView.Selected <> nil then
begin
TreeView.Items.AddChild( TreeView.Selected, sNombre );
TreeView.Selected.Expanded := True;
end
else
TreeView.Items.Add( nil, sNombre );
end;
end;

Lo que hace este procedimiento es preguntarnos el nombre del nodo y si el usuario ha seleccionado uno anteriormente lo mete como hijo (AddChild) expandiendo además el nodo padre (Expanded) como si el usuario hubiese pulsado el botón + del elemento padre.

MODIFICANDO LOS ELEMENTOS DEL ARBOL

Una vez creado un árbol de elementos se puede modificar el texto de cada uno de ellos mediante la propiedad Text. Vamos a hacer que si el usuario pulsa el botón Modificar y hay un nodo seleccionado el programa nos pregunte el nuevo nombre del nodo y lo cambie:

procedure TFTreeView.BModificarClick( Sender: TObject );
var
sNombre: string;
begin
if TreeView.Selected <> nil then
begin
sNombre := InputBox( 'Crear un nodo', 'Nombre:', TreeView.Selected.Text );

if sNombre <> '' then
TreeView.Selected.Text := sNombre;
end;
end;

Cuando se van a hacer operaciones con los nodos hay que asegurarse siempre que el nodo al que vayamos a acceder no sea nil, para evitar Access Violations.

ELIMINANDO LOS ELEMENTOS DEL ARBOL

Para eliminar un nodo del árbol se utiliza el método Delete:

procedure TFTreeView.BEliminarClick( Sender: TObject );
begin
if TreeView.Selected <> nil then
TreeView.Selected.Delete;
end;

Y si queremos eliminar todos los nodos se utiliza el método Clear de la propiedad Items:

procedure TFTreeView.BBorrarTodosClick( Sender: TObject );
begin
TreeView.Items.Clear;
end;

ORDENANDO LOS NODOS ALFABETICAMENTE

El modo de ordenar los elementos de un componente TreeView es igual al de ordenar los elementos de un componente ListView. Hay dos métodos: CustomSort y AlphaSort. El método CustomSort no voy a explicarlo ya que lo mencioné anteriormente en el artículo dedicado al componente ListView y es un poco más primitivo que utilizar AlphaSort.

Para ordenar todos los elementos de un árbol TreeView se utiliza el método:

procedure TFTreeView.BOrdenarClick( Sender: TObject );
begin
TreeView.AlphaSort( True );
end;

El parámetro booleano especifica si queremos que ordene tanto los elementos padres como los hijos (True) o sólo los elementos padres. Si no se especifica nada se asume que ordene todos los elementos.

Ahora hay que programar el evento OnCompare del TreeView para que ordene alfabéticamente los elementos:

procedure TFTreeView.TreeViewCompare( Sender: TObject; Node1,
Node2: TTreeNode; Data: Integer; var Compare: Integer );
begin
Compare := CompareText( Node1.Text, Node2.Text );
end;

Si queremos que la ordenación sea descendente entonces sólo hay que cambiar el signo:

Compare := -CompareText( Node1.Text, Node2.Text );

GUARDANDO LA INFORMACION DEL ARBOL EN UN ARCHIVO DE TEXTO

La clase TTreeView dispone del método SaveToFile para volcar todos los nodos en un archivo de texto para su posterior utilización. Voy a hacer un procedimiento que pregunte al usuario que nombre deseamos dar al archivo y lo guardará en el mismo directorio del programa con la extensión .TXT:

procedure TFTreeView.BGuardarClick( Sender: TObject );
var sNombre: string;
begin
sNombre := InputBox( 'Crear un nodo', 'Nombre:', '' );

if sNombre <> '' then
TreeView.SaveToFile( ExtractFilePath( Application.ExeName ) + sNombre + '.txt' );
end;

La información la guarda por líneas donde cada elemento hijo va separado por tabuladores:

documentos
ventas
contactos
Pablo
Ana
Maria
claves
Terra
Hotmail
GMail

CARGANDO LA INFORMACION DEL ARBOL GUARDADA ANTERIORMENTE

Para cargar el archivo de texto vamos a crear en tiempo real el componente TOpenDialog para que le pregunte al usuario el archivo de texto a cargar:

procedure TFTreeView.BCargarClick( Sender: TObject );
var
Abrir: TOpenDialog;
begin
Abrir := TOpenDialog.Create( Self );
Abrir.InitialDir := ExtractFilePath( Application.ExeName );
Abrir.Filter := 'TreeView|*.txt';

if Abrir.Execute then
TreeView.LoadFromFile( Abrir.FileName );

Abrir.Free;
end;

Hemos modificado el filtro de la carga para que sólo se vean archivos TXT.

En el próximo artículo seguiremos viendo más propiedades interesantes del componente TreeView.

Pruebas realizadas en Delphi 7.

Publicidad