Delphi paso a paso (V): Controles (III) Tipos de ListBox

Anuncio
Delphi paso a paso (V): Controles (III)
Por Vladimir Algara
Como ya se anunció en el número anterior de Algoritmo, en este artículo se abordará la forma
de manipular las funcionalidades de los ListBox y así solucionar muchas de las necesidades que
se presentan a la hora de perfilar una aplicación.
Recordando lo visto hasta ahora acerca de ListBox, saber que partimos de una colección de
datos almacenados en forma de tabla, que podemos rellenar a nuestro gusto (manualmente o
leyendo los datos almacenados en un archivo). Esta fuente de la que obtener los datos, como
veremos más adelante, no se va a quedar anclada aquí, todo lo contrario, se va a caracterizar
por su diversificación.
Una vez relleno el ListBox, podía ser ordenado o restaurado según el original, así como aplicarle
cualesquiera de las propiedades y acciones comunes a los controles, a saber, inhabilitar,
redimensionar, ocultar, etc.
Resumiendo, no hemos visto gran cosa de lo controles tipo ListBox.
A partir de que se conozcan más formas de rellenar controles de tipo ListBox, se irán viendo
más funcionalidades y más ventajas, y ése, concretamente, es el cometido del presente artículo,
por lo tanto, me voy a dejar de zarandajas y me meteré en el meollo de la cuestión, porque ya lo
dijo..., bla, bla, bla..., etc.,...bla, rebla.
Tipos de ListBox
Los ListBox, o sus hermanos los ComboBox, se encuentran en la carpeta Standard y los iconos
que los representan (no seleccionados y seleccionados) son los de la figura 1.
Figura 1. Iconos para ListBox y ComboBox
El nombre (Name) que por defecto se da a un control de tipo ListBox es ListBox1, ListBox2,
etc., y esto será lo primero que iremos cambiando, pues ello permitirá una mejor localización e
identificación posterior (en el ejemplo final vamos a manipular hasta un total de tres listas
deslizantes).
Existen otros tipos de ListBox, diferentes a los que vienen en la paleta Standard, de ellos vamos
a ver dos, uno destinado a mostrar un árbol de los directorios del disco y otro para ver los
archivos de un directorio específico.
Con ambos dos y con uno estándar, construiremos una ventana en la que se podrá teclear el
nombre y/o la extensión de los archivos que queremos visualizar (será en un control de edición).
De acuerdo al nombre escrito allí se almacenará en un ListBox de la clase TFileListBox la
relación de todos los archivos que cumplan la condición de la máscara, para facilitar la
navegación por los distintos directorios se recurrirá a un ListBox de la clase TFileListBox y para
tener una relación de los archivos que se vayan seleccionando se utilizará un ListBox de la clase
TListBox (el estándar). Dado que este ListBox final va a tener un filtro de todos aquellos archivos
que han merecido nuestra atención, si partimos de que los archivos a tratar van a ser BitMaps,
podemos completar el ejemplo haciendo que el BitMap elegido se visualice por pantalla.
1
Algoritmo. La revista para el programador de sistemas de bases de datos. http://www.eidos.es - © Grupo EIDOS
Para resumir, y como soy consciente de que la explicación escrita no ha quedado nada clara,
muestro en la figura 2 la pantalla a la que quiero llegar.
Figura 2. Pantalla ejemplo de ListBox
Nota: Los distintos elementos disponibles son: Un control de edición donde especificar el tipo de
archivos que se quieren visualizar (opción por defecto *.bmp), un ListBox con la estructura de
directorios de nuestra unidad, otro ListBox con los archivos que cumplen la máscara (*.bmp) del
directorio elegido (existe también una parte donde se especifica en qué directorio nos
encontramos -en verde en la ventana-), otro ListBox con los elementos elegidos en el anterior y
una pantalla de visualización del bitmap elegido.
Propiedades de los ListBox
Como viene siendo habitual, hacemos un rápido recorrido por eventos y propiedades no vistos
por el momento, y que están íntimamente ligados a los ListBox. En primer lugar se van a
comentar las propiedades de los controles TFileListBox y a continuación los de
TDirectoryListBox.
Propiedades de TFileListBox
FileEdit. Es una propiedad (dato) con la que se asocia, de manera automática, un ListBox a
un control de edición. El objetivo de esta operación es que, a medida que nos vamos
moviendo por el ListBox o seleccionamos alguno de sus datos, el contenido del control de
edición se amolda a la operación realizada en el ListBox, quedando ambos controles, pues,
sincronizados. Dado que a medida que añadimos controles en una ventana éstos se van
registrando, si pinchamos sobre la propiedad comentada (FileEdit) aparecerá una relación
de los controles de edición disponibles hasta el momento, nuestra misión es elegir alguno
de ellos y echarlo a andar; nada más sencillo.
FileType. Tipos de archivos a visualizar según sus atributos. Se trata de una estructura en
la que se puede elegir entre los distintos tipos de la tabla 1.
2
Algoritmo. La revista para el programador de sistemas de bases de datos. http://www.eidos.es - © Grupo EIDOS
Valor
ftReadOnl
y
ftHidden
ftSystem
ftVolumeID
Significado
Atributo de Sólo Lectura
Atributo de Oculto
Atributo de Archivo del Sistema
Muestra la etiqueta del volumen
seleccionado
ftDirectory Atributo de directorio
ftArchive
Atributo de Archivo
ftNormal
Archivo sin atributos
Tabla 1. Tipos de archivos según los atributos
Mask. Máscara por defecto de los archivos que se van a mostrar en el ListBox. Si se deja
en blanco no se produce filtrado y, por lo tanto, se manipulan todos los archivos. Para
nuestro ejemplo se puede rellenar con *.bmp.
ExtendedSelect. En un ListBox se pueden elegir un elemento o varios (para ello hay que
modificar la propiedad MultiSelect), y se puede hacer sin más que ir pinchando aquellos que
queramos seleccionar o deseleccionar, o bien, siguiendo las técnicas estándar de Windows,
en las que pulsando la tecla [Ctrl] se eligen elementos dispersos y presionando [Shift] un
rango de ellos. ExtendedSelect permite definir cómo se va a comportar este modo de
selección.
MultiSelect. Permite que se pueda elegir más de un ítem entre los de una relación. La
opción por defecto es false.
Propiedades de TDirectoryListBox
DirLabel. De la misma manera que un control de tipo TFileListBox es posible asociarlo a un
control de edición (a través del dato FileEdit), un control de tipo TDirectoryListBox se puede
asociar a un control de tipo TLabel (texto fijo en pantalla). Como antes, el objetivo de esta
operación es tener ambos controles sincronizados, y que la operación producida en el
primero repercuta en el segundo. En el ejemplo de la figura 2 se ha incluido el texto dentro
de un recuadro verde, con la intención de que quede más bonito, objetivo que no se
consigue.
FileList. A través de esta propiedad se permite otra sincronización más. En este caso el
control objeto de sincronización es uno del tipo TFileListBox. Dado que un TFileListBox
posee una máscara de entrada (visto más arriba), si sincronizamos un TDirectoryListBox
con un TFileListBox, éste se rellenará automáticamente cada vez que naveguemos por
aquél.
Obsérvese lo fácil que resulta realizar una ventana que vaya dando cuenta de cada uno de
nuestros movimientos por los directorios, todo sin trazar una línea de código.
Ejemplo de visualización de BitMaps
Los pasos a seguir para obtener la ventana del ejemplo han sido:
1.- Pinchamos en los controles TLabel para poner el literal deseado en cada uno y, en el caso
del que está enmarcado en la caja verde, para cambiar su fuente (Arial, 8 Bold y color
3
Algoritmo. La revista para el programador de sistemas de bases de datos. http://www.eidos.es - © Grupo EIDOS
clWhite) y su color de fondo (clGreen).
2.- Elegimos los controles de edición TEdit para habilitar un lugar donde especificar la máscara
de los archivos a visualizar. Si bien este control lo podríamos asociar al ListBox de archivos,
no lo haremos, pues la funcionalidad que se le dará será, a mi juicio, más interesante que el
mero hecho de la sincronización. Dado que al ubicar un control de edición éste se rellena
automáticamente con el literal Edit1 modificaremos su propiedad Text para dejarlo en
blanco o, siguiendo un criterio que más interesante, lo rellenaremos con *.bmp.
3.- Elegimos un control TFileListBox. Se puede comprobar que se permite su asociación con
cualquier control de edición presente en la ventana, y en concreto con el que hemos puesto
en el paso 2.
4.- Elegimos un control TListBox que se rellenará cuando elijamos, haciendo doble clic, desde
el ListBox del paso 3.
5.- Elegimos un control TDirectoryListBox y lo asociamos mediante su propiedad DirLabel con
el control de edición de la caja verde (a todo esto, la caja verde se hace con un control de
tipo TShape, que se encuentra en la paleta Additional), y asociamos su propiedad FileList
con el ListBox del paso 3. ¡Buf!.
6.- Sin trazar una sola línea de código ya tenemos mucho. Se puede poner en marcha y ver el
resultado de las distintas componentes de la ventana.
7.- Para completar un poco la aplicación y para que no sea Delphi el único que trabaje, se van
a añadir un par de botones, uno de cerrar ventana y otro para visualizar el BitMap del
ListBox del paso 4 (también se podrá visualizar haciendo doble clic sobre el ListBox).
Para la ubicación y manipulación de archivos gráficos existe un control que se encarga de
ellos, este control es de la clase TImage. Un control de este tipo permite, entre otras
cosas, ajustar el BitMap a su tamaño o sólo visualizar, en el área definida, aquella porción
que quepa.
Alguna de las propiedades más importantes de los controles TImage, o al menos aquellos
que vamos a manejar en este ejemplo, son:
-
AutoSize. Obvia el tamaño prefijado del control TImage, de tal forma que si el archivo
gráfico a visualizar es mayor que el área definida, ésta se ignora y el BMP ocupa el
total de su tamaño. Esto puede provocar, incluso, que ni la ventana pueda albergarlo,
por lo que, automáticamente, aparecerán en dicha ventana las barras de
desplazamiento oportunas.
-
Center. Centra la imagen en el área definida, si no la sitúa en el ángulo superior
derecho.
-
Picture. Mediante esta propiedad se asigna al control la imagen que se quiere
visualizar. Dado que lo que se pretende hacer es volcar el contenido de una imagen
seleccionada por nosotros, en este ejemplo se dejará en blanco dicha propiedad
Picture, y se asignará, en tiempo de ejecución, de la siguiente forma:
Imagen.Picture.LoadFromFile( <Archivo> );
-
Stretch. Obliga a que el BMP se ajuste al tamaño fijado o, de no caber, se visualice
sólo lo que quepa en el área definida. Esta propiedad, que en principio es muy potente,
puede hacer que un BMP de gran tamaño quede reducido y distrosionado
excesivamente al ubicarlo en un recinto excesivamente pequeño. En nuestro caso lo
vamos a dejar a false, cediendo el control del tamaño a otro control auxiliar.
4
Algoritmo. La revista para el programador de sistemas de bases de datos. http://www.eidos.es - © Grupo EIDOS
Precisamente porque los archivos gráficos pueden ser enormes o pequeños, apaisados u
horizontales, alargados, etc., sería bueno reservar esa famosa zona de pantalla donde
ubicar el archivo, independientemente del formato de éste. Para este cometido se va a
recurrir a un control del tipo TScrollBox, y dentro de él ubicaremos la imagen (TImage).
La operativa a seguir es ubicar, en primer lugar, un TScrollBox y después un TImage dentro
de él. Esto hace que el control TImage quede constreñido al control padre y que, en ningún
caso, se pueda escapar de su recinto. Las propiedades que nos pueden interesar en los
controles de tipo TScrollBox son:
-
-
AutoScroll. Pone, de manera automática y cuando sea necesario, barras de
desplazamiento vertical y horizontal. Poniéndolo a true conseguimos que, cuando la
imagen sea menor que el recuento definido, aparezca en su totalidad, y cuando no,
podamos desplazarlos para verla en su totalidad.
-
BorderStyle: Tipo de marco que se va a utilizar, según los valores bSingle (tal como
aparece en la figura 2) y bNone (sin marco).
Una vez ubicado el control TImage dentro de la caja TScrollBox hacemos que aquél se
ajuste al tamaño total de éste, lo cual se puede consigue con la propiedad Align de
TImage. Asignando a Align la constante alClient forzamos que toda la imagen se amolde al
tamaño de la caja, pero existe un pero; si visualizamos la imagen en tiempo de ejecución no
vamos a conseguir que aparezcan las mencionadas barras de desplazamiento. Estas
barras sólo aparecen cuando la propiedad Align está a alNone. Por lo tanto, en primera
instancia, podemos elegir alCliente (lo cual provocará que el editor de ventanas se
encargue de colocar y redimensionar TImagen a los contornos de la caja) e inmediatamente
después cambiarlo a alNone, para conseguir el efecto deseado en tiempo de ejecución.
8.- Accedemos a los eventos del botón de visualización, concretamente a OnClick, para que al
pulsar sobre el Botón de Ver se muestre el contenido del archivo gráfico elegido. A este
procedimiento se le ha llamado VerBmp y su contenido es el del fuente 1. En él se inicializa
la variable nPos, la cual servirá para determinar qué elemento del ListBox "estándar" (el de
la clase TListBox) se ha elegido.
Una vez que se tiene la posición en nPos la utilizamos para extraer el ítem concreto, todo
ello a través del dato Items del ListBox (consistente en una cadena de caracteres
organizada en forma de tabla o array)
ListBox2.Items[nPos]
Esto hará que dispongamos del nombre del archivo y su ruta, que es lo que efectivamente
se guarda en la lista deslizante.
// --- Fuente 1 --------------------------------------------------------procedure TForm1.VerBmp(Sender: TObject);
var
nPos: integer;
begin
nPos := ListBox2.ItemIndex;
Imagen.Picture.LoadFromFile( ListBox2.Items[nPos] );
end;
5
Algoritmo. La revista para el programador de sistemas de bases de datos. http://www.eidos.es - © Grupo EIDOS
Si partimos de que no sólo queremos visualizar el BMP cuando pulsemos el botón de Ver,
sino también al hacer doble clic en el ListBox, habrá que manipular el evento OnDblClick de
dicho ListBox. Dado que la operación que hay que realizar en este caso es idéntica a la que
se hace cuando pulsamos el botón de Ver, basta con asociar el mismo procedimiento
VerBMP ya existente, y que es el que está definido en el fuente 1.
-
Ambos llaman al mismo procedimiento, por lo que en el OnClick del botón Ver y el
OnDblClick del ListBox aparecerá la llamada a VerBmp.
9.- Accedemos a los eventos del control de edición, para que cada vez que allí se escriba algo,
ese algo se asuma como máscara del TFileListBox. El evento que hay que manipular es
OnChange del control de edición, donde ensayaremos lo que se ve en le fuente 2.
Por medio del dato Text del control de edición (en nuestro caso EditDir) accedemos al
contenido del control (lo que hay escrito en ese preciso instante). Con ello modificamos la
máscara actual, lo cual se hace alterando el contenido del dato Mask de TFileListBox (en
nuestro caso BMPListBox).
// --- Fuente 2 --------------------------------------------------------procedure TForm1.CambiarMascara(Sender: TObject);
begin
BMPListBox.Mask := EditDir.Text;
end;
10.- Por último, queda habilitar un método que permita transferir el dato seleccionado en el
ListBox de archivos al ListBox estándar. Comúnmente esta operación se realiza tras hacer
doble clic en el elemento deseado, por lo que, nuevamente, habrá que manipular el evento
OnDblClick, esta vez del TFileListBox.
Si al procedimiento lo llamamos Exportar, bastará con escribir esto en la casilla asociada a
OnDblClick y pulsar [Intro]; en la porción de código que aparecerá seguidamente añadimos
las líneas que nos interesan.
Como habíamos comentado en las líneas de más arriba, los elementos de un ListBox se
almacenan en el dato Items, pero cuando manipulamos un ListBox de archivos está
disponible otro dato adicional llamado FileName, donde se almacena la unidad, directorio,
nombre y extensión del archivo (toda la ruta). Bastará con decir:
BMPListBox.FileName;
Para disponer del dato que nos interesa.
Como vimos en el artículo anterior, para añadir datos a un ListBox se había de recurrir al
método Add, pasándole como parámetro la cadena a añadir, por lo tanto:
cCadena := BMPListBox.FileName;
ListBox2.items.Add( cCadena );
Donde cCadena habrá que inicializarla. En caso de no querer utilizar una variable
intermedia, bastará con sustituirlo por su valor efectivo.
6
Algoritmo. La revista para el programador de sistemas de bases de datos. http://www.eidos.es - © Grupo EIDOS
Ya que estamos en el procedimiento invocado cada vez que se hace doble clic en el ListBox
de archivos, podría ser aquí, también, donde se habilitara o no el botón de VerBMP. Como
sabemos, este botón se encarga de mostrar el BMP seleccionado en el ListBox, pero si
ocurriera que ese ListBox no contuviese aún ningún elemento, intentaría ver "algo" que aún
no existe, provocando un error de programa. Para evitar esta situación se puede inhabilitar
inicialmente el boton de Ver, y sólo habilitarlo en el método Exportar que estamos
perfilando.
PBVer.Enabled := true
Resumiendo, el procedimiento Exportar quedará como se ve en el fuente 3
// --- Fuente 3 --------------------------------------------------------procedure TForm1.Exportar(Sender: TObject);
begin
ListBox2.items.Add( BMPListBox.FileName );
PBVer.Enabled := true
end;
Obsérvese en el fuente 3 cómo no se realiza ningún control sobre el elemento que se va a
volcar; esto quiere decir que podremos transferir un mismo archivo tantas veces como
doble clic hagamos en el TFileListBox. Este control se puede realizar recorriéndose el
ListBox de archivos y comprobando su existencia, del resultado de dicha verificación
dependerá que el elemento se transfiera o no.
Sabemos que los elementos del ListBox se almacenan en el dato Items, y que éste
pertenece a la clase TString, por lo que se podrá hacer uso de cualquiera de sus métodos
y datos. Uno de ellos es IndexOf, encargado de buscar una cadena dentro de un TString.
Cuando IndexOf encuentra la cadena buscada, devuelve la posición que ocupa (siendo 0 la
primera de ellas, 1 la segunda y así sucesivamente). Cuando IndexOf devuelve -1 quiere
decir que la cadena buscada no se encuentra. Será en este caso, y no en otro, cuando
habremos de transferir la información.
Si vemos el contenido del fuente 4, que no es más que una ligera modificación sobre el
fuente 3 para tener en cuenta esta eventualidad, sabremos qué quiero decir.
// --- Fuente 4 --------------------------------------------------------procedure TForm1.Exportar(Sender: TObject);
begin
if ListBox2.Items.IndexOf( BMPListBox.FileName ) = -1 then
begin
ListBox2.items.Add( BMPListBox.FileName );
PBVer.Enabled := true
end
end;
Conclusión
7
Algoritmo. La revista para el programador de sistemas de bases de datos. http://www.eidos.es - © Grupo EIDOS
Concluir con Delphi es muy sencillo, pero también muy repetitivo. Se trata de un lenguaje y una
arquitectura que con poquísimas líneas de código permite realizar grandes cosas. En este
ejemplo, sin ir más lejos, se lanzó un programa en el que interactuaban una serie de controles,
todo ello gestionado desde el editor; fue después, tratando de encontrarle las cosquillas, cuando
tuvimos que escribir la friolera de 9 líneas de código, de las cuales, si omitimos la variable (que
solo está puesta por dar algo más de claridad al código), los begin y los end, se nos quedan en
5.
Esto, en mi tierra, es hacer las cosas bien.
8
Algoritmo. La revista para el programador de sistemas de bases de datos. http://www.eidos.es - © Grupo EIDOS
Descargar