El
siguiente ejemplo es una aplicación que se comunica con los usuarios
mediante una ventana o forma de interfaz gráfica. Al igual que el
ejemplo HolaLee , este programa simula
la parte de un Sistema de Información que captura datos personales
de alumnos. Para Delphi es un proyecto construido en forma visual con su
ambiente de desarrollo. Si el programador lo desea, puede establecer además
comunicación con los usuarios en modo "Consola", mediante el uso
de los procedimientos Read, ReadLn, Write, WriteLn, lo cual puede ser útil
en la fase de pruebas de programas. Para ello basta con compilar la aplicación
bajo la Opción "Generate Console Application" o colocando la directiva
al compilador {$APPTYPE CONSOLE}. (Por defecto la directiva que aplica
es la {$APPTYPE GUI}).
La construcción de un Proyecto (Project) con interfaz gráfica (GUI) comienza siempre con la construcción de la Forma. Delphi va generando los archivos del Proyecto. Después el programador va agregando código de programación ObjectPascal a los procedimientos de respuesta de los Eventos de los usuarios, según el plan de la aplicación. Puede agregar sus propias declaraciones y procedimientos, incluyendo nuevas Clases con sus métodos. En una aplicación compleja puede agregar más Formas. Por cada Forma se genera una Unit (archivo o módulo OP con declaraciones y código de programación). También puede agregar Units sin formas asociadas. Con este ejemplo se muestra otra manera de hacer las cosas. Se intenta no sólo desarrollar una aplicación para una necesidad particular sino a la vez planificar y desarrollar recursos programados reusables para un dominio de aplicación (contexto organizacional) en el que ella se inserta. La planificación y diseño (Arquitectura de software) busca: standarizar uso del almacenamiento y procedimientos, resguardar la integridad de los datos, facilitar el desarrollo de futuras aplicaciones o sistemas de información, permitir enfrentar el desarrollo de aplicaciones y sistemas de gran complejidad, facilitar la verificación y el mantenimiento de aplicaciones y sistemas . El paradigma de Programación Orientada a Objetos (OOP), soportado en Delphi y otros lenguajes, permite el logro de esos objetivos con gran eficiencia. También este ejemplo muestra en forma simple la aplicación de un criterio arquitectónico muy productivo en Computación: el diseño e implantación (arquitectura e ingeniería) por capas o niveles.Cada capa consiste en uno o más Librerías que proporcionan un conjunto de recursos y servicios. Las capas a bajo nivel o básicas proporcionan recursos y servicios de propósito general mientras que capas a niveles más altos proporcionan recursos y servicios cada vez más especializados y orientados a dominios particulares. Con la OOP en las librerías se definen jerarquías de Clases de Objetos extensibles o adaptables en librerías de capas superiores. El concepto de Objeto integra en un solo ente recursos (atributos) y servicios (métodos). En el lenguaje ObjectPascal de Delphi las librerías se construyen como módulos tipo Unit o como módulos tipo Library. Las Units al compilarse generan archivos de extensión .dcu (Delphi Compiled Unit), que se enlazan en tiempo de compilación con la aplicación. |
Delphi
proporciona una extensa jerarquía de Clases en diversas Units. Uno
de los beneficios esperados de la OOP es que desarrolladores independientes
distribuyan Librerías con Clases aprovechables por otros desarrolladores
para facilitar la construcción de aplicaciones complejas. El trabajo
necesario para desarrollar librerías de niveles genéricos
se compensa ampliamente con la facilidad para desarrollar y mantener aplicaciones
complejas, más especializadas, a niveles superiores.
El
contenido de los archivos se muestra en forma de tablas, en la columna
izquierda el código en ObjectPascal y en la derecha explicaciones
y comentarios. En los archivos de programa (.dpr y .pas),
las líneas que son generadas automáticamente por Delphi están
en color amarillo; en blanco sólo las que el programador tuvo que
agregar. Aparecen resaltadas en ambos casos las palabras reservadas de
ObjectPascal, tal como lo hace el Editor de Delphi.
DatosValidos.pas: es una Unit que contiene la definición de la jerarquía de clases de datos diseñada para soportar manejo de diversos tipos de datos con integridad. Tiene un diseño genérico, para que pueda ser aplicable a cualquier dominio. Como ejemplo sencillo de aplicación del criterio de desarrollo por capas, corresponde a una capa de nivel básico, que utiliza a su vez, como todos los demás archivos, las librerías de las capas aún más básicas proporcionadas por Delphi. Alumno.pas:
es una Unit que contiene la definición de una clase diseñada
(en forma muy simplificada) para el manejo del tipo de entes asociados
al dominio de la aplicación particular: alumnos de un postgrado.
Como capa utiliza las clases definidas en DatosValidos.pas para
definir la clase TAlumno que queda disponible para
HolaFormaU.pas: es la Unit que contiene la programación correspondiente a la forma de interfaz de usuario del proyecto particular. Como capa, corresponde al nivel más alto utilizado en el proyecto, utilizando a su vez la clase definida en Alumno.pas. HolaFormaU.dfm: es parte de la visualización en modo texto de la Forma diseñada por el programador como interfaz de usuario. Este archivo de extensión .dfm (Delphi ForM) contiene las declaraciones correspondientes al diseño de la Forma; es generado por Delphi transcribiendo la construcción que hace el usuario en forma visual. No hace falta que el programador vea este archivo ni debe modificar manualmente el texto, Delphi se encarga de su actualización cada vez que visualmente se modifique la apariencia o el contenido de la Forma asociada, ya sea por acciones directas sobre la Forma o modificando propiedades con el Object Inspector . HolaForma.dpr: es el archivo raíz o índice del proyecto, de extensión .dpr (Delphi PRoject). |
unit
DatosValidos;
interface uses StdCtrls, Dialogs, Controls, Forms, SysUtils; |
Unit construida por el
programador.
Comienzo de bloque de declaraciones. Units que contienen librerías Delphi utilizadas. |
type
TDatoTexto = class protected pNombreDato: string; pDato: string; pAsignado: boolean; SuEdit: TEdit; public |
Comienzo de
declaraciones de tipos (tipos de datos y clases)
Se define nueva clase, por defecto, hija de
TObject,
clase
raíz de todas las clases en Delphi.
|
constructor Crea(const aNombreDato: string;
aSuEdit:TEdit); constructor CreaInicia(const aNombreDato, aDato: string; aSuEdit:TEdit); |
Un constructor
es
un método especializado para instanciar objetos de la clase.
Toda clase en Delphi tiene al menos un constructor
heredado
de TObject: Create.
Se pueden definir varios.
Observe la declaración de dos métodos constructores. El segundo adicionalmente asigna un valor al dato. |
procedure EntradaDato; virtual; | Observe la declaración
de este método con el calificativo virtual,
que indica que en los objetos de clases descendientes se selecciona siempre
dinámicamente (en tiempo de ejecución) la versión
propia de su clase, aún cuando la referencia se haga con un nombre
de objeto declarado en una clase antecesora.
Esto es Polimorfismo en OOP. |
function
NombreDato: string;
function Dato: string; function Asignado: boolean; |
Función:
Código reutilizable que retorna un valor del tipo especificado.
Métodos-Funciones para obtener los valores de los atributos protegidos. El método-función Asignado retorna verdad cuando se ha registrado un dato que pasa los controles de validación. |
end; | Fin de la declaración de la clase. |
TDatoCuantitativo = class (TDatoTexto)
protected limI, limS: double; ValorNumerico: double; pUnidad: string; procedure Valida; |
Clase descendiente de TDatoTexto
para registrar y validar datos numéricos. Diseñada para manejar
tipo de dato double,
el tipo real más general en Delphi después del extended.
Sus descendientes pueden diseñarse para soportar otros tipos numéricos.
(En Delphi el tipo Pascal real equivale a double, ver real types en el Help de Delphi) Para datos numéricos se registra Rango de validez, valor asignado válido (ValorNumerico) y nombre de Unidad de medición del dato. El método Valida aplica los controles de validación. |
public | El resto tiene acceso público (sin rectricción) |
constructor Crea(const aNombreDato: string;
aSuEdit:TEdit; alimI, alimS: double; const aUnidad: string); |
Al crear un objeto de la clase, se define el Rango de validez y la Unidad de medición. También se establece la relación, através del parámetro aSuEdit con un control de tipo TEdit donde el usuario escribe el dato que el método EntradaDato recoge. |
procedure EntradaDato; override; | El calificativo override indica que ésta es la versión polimórfica del método virtual definido en TDatoTexto. |
function
LimiteInferior: double;
function LimiteSuperior: double; function Valor: double; function Unidad: string; |
Siguen las definiciones de métodos-funciones para obtener los valores de los atributos protegidos. |
end; | Fin de la declaración de la clase. |
TDatoEntero = class(TDatoCuantitativo)
protected pValor: integer; public constructor CreaInicia( const aNombreDato,aDato: string; aSuEdit: TEdit; alimI, alimS: double; const aUnidad: string); |
Definición de descendiente
de TDatoCuantitativo
para datos tipo entero.
Se agrega un atributo para guardar el valor entero. Se agrega un constructor propio para inicializar valor de dato. const indica que los parámetros son referencias a variables no modificables definidas en el entorno que invoque al método. Los valores de parámetros sin calificativo se guardan localmente y sólo son modificables internamente. |
procedure EntradaDato; override; | Versión polimórfica del método EntradaDato. |
function Valor: integer; | Se redefine la función
Valor,
para entregar entero.
Un método que se declara con el mismo nombre de uno ya existente en la clase o en alguna antecesora, pero con diferente encabezado (lista de parámetros o tipo de resultado si es función), se interpreta como un método distinto. Se dice en OOP que se hace sobrecarga (overload) del nombre. |
end; | Fin de la declaración de la clase. |
TDatoSimple = class(TDatoCuantitativo)
protected pValor: single; public |
Definición de otro descendiente de TDatoCuantitativo para datos tipo simple. Se agrega un atributo para guardar el valor simple (simple precisión, ver real types en Help) |
constructor
CreaInicia(
const aNombreDato,aDato: string; aSuEdit: TEdit; alimI, alimS: double; const aUnidad: string); |
Constructor propio para inicializar valor de dato. |
procedure
EntradaDato; override;
function Valor: single; end; |
Versión polimórfica
del método EntradaDato.
Se redefine la función Valor, para entregar single. Fin de la declaración de la clase. |
TDatoDoble = class(TDatoCuantitativo)
public constructor CreaInicia( const aNombreDato,aDato: string; aSuEdit: TEdit; alimI, alimS: double; const aUnidad: string); procedure EntradaDato; override; |
Definición de otro
descendiente de TDatoCuantitativo
para datos tipo doble.
TDatoCuantitativo ya registra dato tipo double. Sólo hay que definir el constructor CreaInicia y el método polimórfico EntradaDato. |
end; | Fin de la declaración de la clase. |
implementation
var coderr: integer;
|
Comienzo de bloque de implementación de métodos de las clases definidas y de procedimientos y funciones no asociados a ninguna clase. En esta sección también puede definirse variables internas a la Unit. En este caso se define una variable global interna que guarda el estado de la última validación de datos. |
constructor
TDatoTexto.Crea(
const aNombreDato:string; aSuEdit:TEdit); begin inherited Create; pNombreDato:=aNombreDato; pDato:=''; pAsignado:=false; SuEdit:=aSuEdit; end; |
Codificación del
primer constructor de la clase TDatoTexto.
Recibe valores de la referencia al Nombre que se asigna al Objeto y al de la referencia al TEdit asociado. Lo primero que hay que hacer es invocar al método constructor heredado (inherited) de su antecesor inmediato, la clase TObject, para que Delphi se encargue de la tarea inicial de creación. Después se agrega lo específico de la nueva clase, en este caso, guardar los valores de los parámetros en atributos protegidos. |
constructor
TDatoTexto.CreaInicia(
const aNombreDato, aDato: string; aSuEdit:TEdit); begin Crea(aNombreDato,aSuEdit); pDato:=aDato; pAsignado:=true; end; |
Codificación del
segundo constructor de la clase TDatoTexto.
Invoca al otro constructor y luego agrega lo específico de este constructor, que es la asignación de valor al dato. |
procedure
TDatoTexto.EntradaDato;
begin pAsignado:=true; pDato:=SuEdit.Text; if pDato='' then pAsignado:=false; end; |
Cada clase descendiente
puede definir su propia versión polimórfica del procedimiento
EntradaDato.
Toma el valor textual del dato de la propiedad Text del TEdit asociado. Si es vacío, lo da por no asignado. |
function
TDatoTexto.NombreDato: string;
begin Result:=pNombreDato; end; function TDatoTexto.Dato: string; begin Dato:=pDato; end; function TDatoTexto.Asignado: boolean; begin Result:=pAsignado; end; |
Codificación
de funciones para acceder a los valores de atributos protegidas (protected).
Ver en el Help de Delphi la declaración de tipo de atributo property, que hubiera podido usarse alternativamente en en el caso de estos atributos. |
constructor
TDatoCuantitativo.Crea(
const aNombreDato: string; aSuEdit: TEdit; alimI, alimS: double; const aUnidad: string); begin inherited Crea(aNombreDato,aSuEdit); ValorNumerico:=0; if alimI <=alimS then begin limI:=alimI; limS:=alimS; end else if MessageDlg('Rango Inválido para '+NombreDato+ '. Se asigna Valor Límite Inferior',mtError, [mbOK,mbCancel],0)=mrOK then begin limI:=alimI; limS:=alimI; end else Application.Terminate; pUnidad:=aUnidad; end; |
Codificación del
constructor de decendiente de TDatoTexto.
Lo primero que hay que hacer es invocar a un método constructor heredado (inherited) de su antecesor inmediato, la clase TDatoTexto. Inicializa al atributo protegido ValorNumerico. Verifica que el rango sea consistente. Si no lo es, se da mensaje en forma interactiva, lo que permite al usuario continuar o cancelar la ejecución. (MessageDlg en Unit Dialogs). Las constantes mrOK, ... están definidas en la Unit Controls.La Clase TApplication lo está en la Unit Forms. Ver HolaFormaU.pas) |
procedure
TDatoCuantitativo.EntradaDato;
begin inherited; coderr:=0; // para validación numérica end; |
Versión polimórfica
del método EntradaDato.
Base para versiones polimórficas de descendientes de la clase TDatoCuantitativo.
Lo primero es invocar a la versión heredada del antecesor. (No hace
falta poner el nombre por ser el mismo).
Observe el comentario estilo C++. |
procedure
TDatoCuantitativo.Valida;
begin if coderr > 0 then begin pAsignado:=false; MessageDlg(pNombreDato+'Inválido', mtError,[mbOK],0); end else if coderr = 0 then if (ValorNumerico < limI) or (ValorNumerico > limS) then begin pAsignado:=false; MessageDlg(pNombreDato+'Fuera de Rango: '+ FloatToStr(limI)+', '+ FloatToStr(limS),mtError,[mbOK],0); end; end; |
Este método se invoca
después de tomado un dato y haberlo convertido a numérico
con el procedimiento Val.
En la variable global coderr
se deja el estado exitoso o fallido de la conversión. Observe que
aunque MessageDlg
es una función, puede invocarse como procedimiento, descartando
el resultado.
Si el dato es numérico, hay que validar además que esté dentro del rango definido. Si no pasa las validaciones, queda no asignado. Observe el uso de FloatToStr, una de las funciones de conversión de Delphi (Unit SysUtils). Ver Help. |
function
TDatoCuantitativo.LimiteInferior: double;
begin Result:=limI; end; function TDatoCuantitativo.LimiteSuperior: double; begin Result:=limS; end; function TDatoCuantitativo.Unidad: string; begin Result:=pUnidad; end; |
Métodos-Funciones que entregan los valores de atributos protegidos. |
function
TDatoCuantitativo.Valor:
double;
begin Result:=ValorNumerico; end; |
Método-Función que entrega el valor numérico double. |
constructor
TDatoEntero.CreaInicia(
const aNombreDato,aDato: string; aSuEdit: TEdit; alimI, alimS: double; const aUnidad: string); begin Crea(aNombreDato,aSuEdit,alimI,alimS,aUnidad); pDato:=aDato; Val(pDato,pValor,coderr); ValorNumerico:=pValor; Valida; end; |
Constructor propio disponible
para cuando se quiere crear e inicializar valor del dato entero. Si no,
basta usar el constructor heredado.
Se aplica primero el constructor heredado, después se toma y valida el valor inicial dado. |
procedure
TDatoEntero.EntradaDato;
begin inherited; Val(pDato,pValor,coderr); ValorNumerico:=pValor; Valida; end; |
Versión polimórfica
del método EntradaDato.
Observe como a partir de la invocación del método heredado
del mismo nombre, se ejecutan hacia atrás los demás de la
subjerarquía que comienza con la clase TDatoTexto.
Se hace la conversión a numérico entero (indicado por el tipo de pValor) y se pasa a validar. |
function
TDatoEntero.Valor: integer;
begin Result:=pValor; end; |
Método-Función que entrega el valor numérico integer. |
constructor
TDatoSimple.CreaInicia(
const aNombreDato,aDato: string; aSuEdit: TEdit; alimI, alimS: double; const aUnidad: string); begin Crea(aNombreDato,aSuEdit,alimI,alimS,aUnidad); pDato:=aDato; Val(pDato,pValor,coderr); ValorNumerico:=pValor; Valida; end; |
Constructor propio disponible
para cuando se quiere crear e inicializar valor del dato simple. Si no,
basta usar el constructor heredado.
Se aplica primero el constructor heredado, después se toma y valida el valor inicial dado. |
procedure
TDatoSimple.EntradaDato;
inherited; Val(pDato,pValor,coderr); ValorNumerico:=pValor; Valida; end; |
Versión polimórfica
del método EntradaDato.
Vale la misma obseración que en la versión para TDatoEntero.
Se hace la conversión a numérico simple (indicado por el tipo de pValor) y se pasa a validar. |
function
TDatoSimple.Valor: single;
begin Result:=pValor; end; |
Método-Función que entrega el valor numérico single. |
constructor
TDatoDoble.CreaInicia(
const aNombreDato, aDato: string; aSuEdit: TEdit; alimI, alimS: double; const aUnidad: string); begin Crea(aNombreDato,aSuEdit,alimI,alimS,aUnidad); pDato:=aDato; Val(pDato,ValorNumerico,coderr); Valida; end; |
Constructor propio disponible
para cuando se quiere crear e inicializar valor del dato doble. Si no,
basta usar el constructor heredado.
Se aplica primero el constructor heredado, después se toma y valida el valor inicial dado. |
procedure
TDatoDoble.EntradaDato;
begin inherited; Val(pDato,ValorNumerico,coderr); Valida; end; |
Versión polimórfica
del método EntradaDato.
Vale la misma obseración que en la versión para TDatoEntero.
Se hace la conversión a numérico doble (indicado por el tipo de ValorNumerico) y se pasa a validar. |
end. | Fin de la Unit. |
unit Alumnos;
interface uses DatosValidos,Dialogs,Forms,StdCtrls,SysUtils; type |
Unit construida por el
programador.
Comienzo de bloque de declaraciones. En la lista de Units de la declaración uses se incluye a DatosValidos (la Unit anterior), que contiene clases que se aplican para definición de tipos de datos. Las demás Units son de Delphi. |
NombreCampos=(Nombre,Apellido, Edad, Peso, Altura); | Tipo enumerado.
Equivale a definir las constantes: Nombre=0,Apellido=1,Edad=2,Peso=3,Altura=4
Se usa para mejor legibilidad del código de programación. |
Editores = array[NombreCampos] of TEdit; | Arreglo de referencias a objetos de tipo TEdit, indizados por los valores de tipo NombreCampos. |
TAlumno
= class
Campos: array[NombreCampos] of TDatoTexto; constructor Crea(const elEdit: Editores); function MostrarDatos: boolean; end; |
Definición de la
clase TAlumno,
descendiente
de TObject, como lo es toda clase por defecto en Delphi. Se define
con un único atributo de tipo múltiple (array).
TDatoTexto
es la clase raíz de la jerarquía de clases definida en DatosValidos
(diversos tipos de datos con aplicación de reglas de validación).
Cada campo se especializará al momento de creación de los
respectivos objetos y para su uso se aprovechará la propiedad de
Polimorfismo
de la OOP.
Un constructor es un procedimiento especializado para instanciar objetos de la clase. Toda clase en Delphi tiene al menos un constructor heredado de TObject: Create. Se pueden definir varios. Función: Código reutilizable que retorna un valor del tipo especificado. |
implementation | Comienzo de bloque de implementación de métodos de las clases definidas y de procedimientos y funciones no asociados a ninguna clase. En esta sección también puede definirse variables internas a la Unit. |
constructor
TAlumno.Crea(const elEdit: Editores);
begin inherited Create; Campos[Nombre]:=TDatoTexto.CreaInicia('Nombre: ', elEdit[Nombre].Text, elEdit[Nombre]); Campos[Apellido]:=TDatoTexto.CreaInicia('Apellido:', elEdit[Apellido].Text,elEdit[Apellido]); Campos[Edad]:=TDatoEntero.Crea('Edad: ', elEdit[Edad],16,80,' años '); Campos[Peso]:=TDatoSimple.Crea('Peso: ', elEdit[Peso],40,120,' Kg. '); Campos[Altura]:=TDatoDoble.Crea('Estatura: ', elEdit[Altura],120,200,' cm. '); end; |
Con el constructor
se
crean y asignan las referencias a los objetos especializados para cada
Campo.
Por
el parámetro elEdit
se le entrega, como arreglo, la lista de las referencias a los controles
TEdit
de la Forma en los que se recibirán los respectivos datos del usuario.
Para comenzar, se invoca al constructor heredado de la clase primitiva TObject. CreaInicia es un constructor de la clase TDatoTexto definida en la Unit DatosValidos. Observe la forma especial de invocar a un constructor: se invoca como método de tipo función, no de un objeto particular ya creado, sino de la clase misma, por su nombre. Devuelve el valor de la referencia al objeto recién creado, el cual se asigna a la variable de tipo referencia a objetos de clase TDatoTexto, a la izquierda. Observe la asignación de clase para los campos que alojarán valores numéricos (usables en expresiones aritméticas). Se aplican constructores de las clases derivadas de TDatoTexto definidas en la Unit DatosValidos. |
function
TAlumno.MostrarDatos: boolean;
var i: NombreCampos; Saludo, Mensaje: string; begin Result:=true; Saludo:='Hola '; Mensaje:='Datos Validados: '; for i:=Nombre to Altura do if not (Campos[i].Asignado) then begin MessageDlg('Entre o corrija su '+ Campos[i].NombreDato,mtError,[mbOK],0); if Campos[i] is TDatoCuantitativo then with TDatoCuantitativo(Campos[i]) do MessageDlg('Rango válido: '+ FloatToStr(LimiteInferior)+', '+ FloatToStr(LimiteSuperior),mtInformation,[mbOK],0); Result:=false; end else begin if Campos[i] is TDatoCuantitativo then with TDatoCuantitativo(Campos[i]) do Mensaje:=Mensaje+NombreDato+Dato+Unidad+' ' else Saludo:=Saludo+' ' + Campos[i].Dato; end; ShowMessage(Saludo); ShowMessage(Mensaje); end; |
Método de tipo función
que devolvuelve truesi
el usuario introduce correctamente todos los datos solicitados en la forma,
si no, devolvuelve
false.
Observe la manera de asignar resultado a una
función. También puede hacerse asignando el valor al nombre
de la función usado como
variable a la izquierda.
Observe el uso de la instrucción for
para recorrer todos los campos definidos.
Al fallar al menos un campo, se asigna resultado
false.
|
end. | Fin de la Unit. |
unit HolaFormaU; | Unit preparada usando la programación visual de Delphi, que genera la declaración de la forma y los esqueletos de los métodos. El progrmador completa y agrega codificación en ObjectPascal. |
interface | Comienzo de bloque de declaraciones. |
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, DatosValidos, Alumnos; |
Lista de Delphi-Units que
contienen Clases de la jerarquía de Clases disponibles en Delphi.
El programador puede agregar Units propias a la lista. Para mejor control del proyecto por parte de Delphi conviene agregar Units existentes, sin o con Formas, con la opciones Add to Projecten el menu Project. En este caso se han agregado las Units anteriores: DatosValidos y Alumnos. Si se quiere crear nueva Unit o nueva Forma con su respectiva Unit, entonces utilice las opciones New Unit o New Form del menú File. |
type
TForm1 = class (TForm) elNombre: TEdit; elApellido: TEdit; Panel1: TPanel; laEdad: TEdit; elPeso: TEdit; laAltura: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; Buton: TButton; |
Delphi genera las declaraciones de los controles y componentes colocados por el programador en la forma y registra en el archivo de la forma (HolaFormaU.dfm en este caso) las propiedades asignadas con el ObjectInspector. |
procedure
Inicial(Sender: TObject);
procedure LimpiaTexto(Sender: TObject); procedure GuardaTexto(Sender: TObject); procedure EntraTexto(Sender: TObject; var Key: Char); procedure Salida(Sender: TObject); procedure SalidaClose(Sender: TObject; var Action: TCloseAction); private { Private declarations } public { Public declarations } |
Delphi genera los encabezados de los métodos que el programador asigna para responder a los eventos seleccionados en cada componente, incluyendo la forma misma. El programador puede agregar otros métodos (procedimientos y funciones) y atributos, públicos o privados. |
end; | Fin de la declaración de la forma. |
var Form1: TForm1; Alumno: TAlumno; LosEditores: Editores; |
Se declaran 3 variables: la primera de tipo referencia a objeto de la clase TForma1, la segunda de tipo referencia a Objeto (instancia) de la clase TAlumno, definida en la Unit Alumnos. La tercera de tipo Editores, definido en Alumnos. Es un tipo array cuyos índices, definidos también en Alumnos, están en correspondencia con los atributos (Campos) definidos para la clase TAlumno. |
implementation
{$R *.DFM} |
Comienzo de bloque de implementación de métodos de las clases definidas y de procedimientos y funciones no asociados a ninguna clase. |
procedure
TForm1.Inicial(Sender: TObject);
begin LosEditores[Nombre]:=elNombre; LosEditores[Apellido]:=elApellido; LosEditores[Edad]:=laEdad; LosEditores[Peso]:=elPeso; LosEditores[Altura]:=laAltura; Alumno:=TAlumno.Crea(LosEditores); end; |
Al iniciarse la ejecución
del programa, Windows activa la Forma, e inmediatamente se ejecuta este
método. (Respuesta al Evento OnActivate).
Aquí se inicializan los elementos del vector (array) con las referencias a los controles de tipo TEdit que se colocaron en la forma para recibir los datos del usuario. Se termina la acción del método con la llamada al método constructor de la clase TAlumno para creae la instancia del objeto, cuya referencia se guarda en la variable Alumno. |
procedure
TForm1.LimpiaTexto(Sender:TObject);
begin TEdit(Sender).Text:=''; end; |
Método de respuesta al evento OnClick en cualquiera de los componentes de tipo TEdit. Observe el uso de casting para especializar el tipo TObject (que es la clase primitiva de todas las clases en Delphi) al tipo TEdit. |
procedure
TForm1.GuardaTexto(Sender: TObject);
begin Alumno.Campos[NombreCampos (TEdit(Sender).Tag)].EntradaDato; end; |
Método de respuesta
al evento OnExit en
cualquiera de los componentes de tipo
TEdit. OnExitse
produce cuando el usuario se cambia de control. También se manda
a ejecutar este procedimiento cuando el usuario termina la entrada de un
dato con la tecla [Enter].
POLIMÓRFICAMENTE se ejecuta la versión de la clase específica que se usó al crear el campo. (Ver constructor de TAlumno en Alumnos). Observe el uso del atributo Tag de TEdit. Delphi proporciona este atributo en los controles para que los programadores puedan asociar un valor numérico entero a cada control. En este caso se usa para hacer que el TEdit sirva como índice del array: TEdit(Sender).Tages un número entre 0 y 4 en este caso; el nombre de tipo NombreCampos se usa de castingal tipo entero del tag para compatibilizarlo con el tipo de índice definido para el arreglo de objetos Campos. |
procedure
TForm1.EntraTexto(Sender:
TObject;
var Key: Char); begin if Key=#13{return} then GuardaTexto(Sender); end; |
Método de respuesta al evento OnKeyPress en cualquiera de los componentes de tipo TEdit. Al recibir el Return se ordena ejecutar el método para asignación del dato. |
procedure TForm1.Salida(Sender:TObject);
begin If Alumno.MostrarDatos then Application.Terminate; end; |
Método de respuesta
al evento OnClick en
el componente de tipo TButton.
Application
es el nombre con el que Delphi designa a la aplicación en proceso.
Es de Clase TApplication;
Terminate es uno de sus métodos. (Unit Forms) |
procedure
TForm1.SalidaClose(Sender:
TObject;
var Action: TCloseAction); begin if Alumno.MostrarDatos then Action:=caFree else Action:=caNone; end; |
Método de respuesta al evento de cerrado de la Forma. Devuelve a Windows en la referencia Action el tipo de acción especificada por el programador: caNone si no se quiere que la aplicación termine; caFree si sí. Con este programa si el usuario termina de entrar correctamente todos sus datos, la aplicación puede terminar (MostrarDatos retorna verdadero). Si no, debe continuar activa hasta que el usuario lo haga. |
end. | Fin de la Unit. |
object Form1: TForm1
................
.............. OnActivate = Inicial OnClose = SalidaClose object elNombre: TEdit
............. Text = 'Alumno' OnClick = LimpiaTexto OnExit = GuardaTexto OnKeyPress = EntraTexto object elApellido: TEdit
Text = ' Postgrado' OnClick = LimpiaTexto OnExit = GuardaTexto OnKeyPress = EntraTexto object Panel1: TPanel .............
Caption = 'Edad' object Label2: TLabel
Caption = 'Peso en Kg.' object Label3: TLabel
Caption = 'Estatura en cm.' object laEdad: TEdit
.............. OnClick = LimpiaTexto OnExit = GuardaTexto OnKeyPress = EntraTexto object elPeso: TEdit
.............. OnClick = LimpiaTexto OnExit = GuardaTexto OnKeyPress = EntraTexto object laAltura: TEdit
.............. OnClick = LimpiaTexto OnExit = GuardaTexto OnKeyPress = EntraTexto object Boton: TButton
Caption = 'Aceptar' TabOrder = 3 OnClick = SalidaBoton object Label4: TLabel ............. Caption = 'Nombre: ' ............. end object Label5: TLabel ............. Caption = 'Apellido:' ............. end; |
El archivo de extensión .dfm corresponde a la definición de esta forma. La forma contiene dos componentes de tipo TEdit, dos componentes de tipo TLabel, un componente de tipo TButton, un componente de tipo TPanel dentro del cual están 3 componentes más de tipo TLabel y 3 componentes más de tipo TEdit. Se muestran sólo porciones del archivo.
Observe
|
program
HolaForma;
uses
{$R *.RES} begin
|
Para proyectos diseñados con formas de interfaz gráfica para usuarios, Delphi genera el archivo de extensión .dpr. En la sección uses coloca los nombres y las ubicaciones de todas las Units incorporadas al proyecto, además de la referencia a la Delphi-Unit Forms, que contiene la Clase TForm, clase primitiva de todas las formas. |