Diferencia entre revisiones de «PRG DELPHI/FRAMES»

De Pragma Wiki
Ir a la navegación Ir a la búsqueda
Sin resumen de edición
 
(No se muestran 21 ediciones intermedias del mismo usuario)
Línea 1: Línea 1:
=Introducción=
=Introducción=
[[Category:MANUAL/PROGRAMADOR]]
[[Category:MANUAL/PROGRAMADOR]]
Los frames de Delphi tienen una definición muy similar a la de los forms permitiendo el agregado de controles visuales (y no visuales) y programando su funcionalidad, pero para mostrarse deben ser 'pegados' en algún otro componente  
[[Category:PRG DELPHI/DESARROLLO]]
visual, por ejemplo, un panel dentro de un form. Es decir, que desarrollamos los frames como si fueran un form, pero la única manera de interactuar con ellos es pegándolos a un componente que lo permita. Los frames son útiles para organizar grupos de controles que se usan en múltiples lugares en la aplicación.
Los frames de Delphi tienen una definición muy similar a la de los forms permitiendo el agregado de controles visuales (y no visuales) y programando su funcionalidad. Pero para mostrarse deben ser 'pegados' en algún otro componente visual, por ejemplo, un panel dentro de un form.  
 
Es decir, que desarrollamos los frames como si fueran un form, pero la única manera de que el usuario interactúe con ellos es pegándolos a un componente que lo permita.  
 
Los frames son útiles para organizar grupos de controles que se usan en múltiples lugares en la aplicación.


Por ejemplo, en Pragma todas las pantallas pueden mostrarse en dentro de la aplicación:
Por ejemplo, en Pragma todas las pantallas pueden mostrarse en dentro de la aplicación:
Línea 74: Línea 78:
[[:Category:PRG DELPHI/CLASES|Definición de clases en Delphi]] puede servir como referencia.
[[:Category:PRG DELPHI/CLASES|Definición de clases en Delphi]] puede servir como referencia.


=Agregando eventos al frame=
=Eventos en el frame=
Un evento es un acontecimiento que ocurre dentro de una aplicación, los eventos pueden vincularse con procedimientos de objetos para que éstos hagan algo cuando sean notificados.
Un evento es un acontecimiento que ocurre dentro de una aplicación, los eventos pueden vincularse con procedimientos de objetos para que éstos hagan algo cuando sean notificados.


Línea 83: Línea 87:
(Ver más sobre eventos en [https://docwiki.embarcadero.com/RADStudio/Sydney/en/Events_(Delphi) Eventos en Delphi]).
(Ver más sobre eventos en [https://docwiki.embarcadero.com/RADStudio/Sydney/en/Events_(Delphi) Eventos en Delphi]).


=Agregar controles al form=
=Agregar controles al frame=
Los controles son objetos visuales que permiten la interacción del usuario con la aplicación tales como:
Los controles son objetos visuales que permiten la interacción del usuario con la aplicación tales como:
*Paneles.
*Paneles.
Línea 90: Línea 94:
*Botones.
*Botones.


Vamos a agregar algunos controles a nuestro form.
Vamos a agregar algo al frame.
 
===Agregar paneles===
Los paneles permiten dividir la pantalla en áreas y pueden contener controles, vamos a agregar dos paneles.


Los controles a agregar al form se pueden seleccionar desde la paleta de herramientas:
===Agregar un checkbox===
[[Archivo:20250507 1506 TOOL PALETTE.png|miniaturadeimagen|no|Paleta de herramientas de Delphi.]]
Un checkbox permite marcar un campo indicando algo, solo tiene 2 valores posibles: marcado o desmarcado.


Agregamos un panel superior llamado PanelDeArriba, y un panel inferior llamado PanelDeAbajo. Ambos están separados por un control denominado TBevel (podría traducirse como bisel) que muestra una separación entre ambos paneles.
Para el desarrollador se ve así:
[[Archivo:20250508 1055 FRAME CON CHECKBOX.png|miniaturadeimagen|no|Un checkbox en un frame.]]


La vista del desarrollador es la siguiente, ya no se ven las marcas en la pantalla porque han sido cubiertos por los paneles:
En el código:
[[Archivo:20250507 1511 FORM CON PANELES DESARROLLADOR.png|miniaturadeimagen|no|Paneles agregados según la vista del desarrollador.]]
 
La del usuario es casi igual:
[[Archivo:20250507 1513 FORM CON PANELES USUARIO.png|miniaturadeimagen|no|Paneles agregados según la vista del usuario.]]
 
El ancho y alto del panel es definible, en este caso el inferior es menos alto que el superior, y ambos están '''alineados''' al form por lo que si modificamos el tamaño de la pantalla también se va a modificar el tamaño de los paneles.
 
El código de estos paneles se ve de la siguiente manera, solo mostramos la interfaz ya que no tienen ninguna programación en la implementación:
<pre>
<pre>
type
type
   TTPersonaForm = class(TForm)
   TTPersonaFrame = class(TFrame)
     PanelDeArriba: TPanel;
     CheckBoxDeAcuerdo: TprxCheckBox;
    Bevel1: TBevel;
    PanelDeAbajo: TPanel;
</pre>
</pre>


Delphi además guarda información en un archivo con detalles sobre el tamaño, alineación y jerarquía de los controles del form, por ejemplo:
El tipo del control es TprxCheckBox que es un checkbox programado en Pragma que deriva de TCheckBox.
 
Delphi además guarda información en un archivo con detalles sobre el tamaño, alineación y jerarquía de los controles del frame, por ejemplo:
<pre>
<pre>
object TPersonaForm: TTPersonaForm
object TPersonaFrame: TTPersonaFrame
   Left = 0
   Left = 0
   Top = 0
   Top = 0
   Caption = 'TPersonaForm'
   Width = 345
  ClientHeight = 382
   Height = 257
  ClientWidth = 598
   TabOrder = 0
  Color = clBtnFace
   object CheckBoxDeAcuerdo: TprxCheckBox
  Font.Charset = DEFAULT_CHARSET
     Left = 64
   Font.Color = clWindowText
     Top = 56
  Font.Height = -11
     Width = 233
   Font.Name = 'Tahoma'
     Height = 14
  Font.Style = []
     Caption = 'Click si est'#225' de acuerdo'
  OldCreateOrder = False
  OnHide = FormHide
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object Bevel1: TBevel
    Left = 0
    Top = 338
    Width = 598
    Height = 3
    Align = alBottom
    ExplicitTop = 291
  end
   object PanelDeArriba: TPanel
     Left = 0
     Top = 0
     Width = 598
     Height = 338
    Align = alClient
    BevelOuter = bvNone
     Caption = 'PanelDeArriba'
     TabOrder = 0
     TabOrder = 0
    ExplicitLeft = 96
    ExplicitTop = 16
    ExplicitWidth = 185
    ExplicitHeight = 41
  end
  object PanelDeAbajo: TPanel
    Left = 0
    Top = 341
    Width = 598
    Height = 41
    Align = alBottom
    BevelOuter = bvNone
    Caption = 'PanelDeAbajo'
    TabOrder = 1
    ExplicitLeft = 104
    ExplicitTop = 224
    ExplicitWidth = 185
   end
   end
end
end
</pre>
</pre>


=Agregar un memo=
=Cómo usar el frame=
Podemos agregar un memo al panel superior para ingresar un texto, la clase se llama TMemo y el componente lo llamaremos Memo1.
Vamos a mostrar el nuevo frame en el form que creamos en [[PRG DELPHI/FORMS|Definición de forms en Delphi]], hay que hacer algunos cambios.


El desarrollador lo vería de la siguiente manera:
Para empezar, vamos a agregar:
[[Archivo:20250507 1537 FORM CON MEMO DESARROLLADOR.png|miniaturadeimagen|no|Un memo en la pantalla en la vista del desarrollador.]]
*Un panel justo debajo del memo que albergará el frame llamado '''PanelParaFrame'''.
*Un botón que picaremos para agregar el frame llamado '''ButtonCrearFrame'''.
El diseñador verá lo siguiente:
[[Archivo:20250508 1158 CAMBIOS AL FORM.png|miniaturadeimagen|no|Cambios al form para abrir el frame.]]


El usuario lo vería casi igual, pero con la posibilidad de introducir texto:
Al botón le agregamos un evento OnClick para que se ejecute cuando lo piquemos, el código es:
[[Archivo:20250507 1539 FORM CON MEMO USUARIO.png|miniaturadeimagen|no|Un memo en la pantalla en la vista del usuario.]]
<pre>
procedure TTPersonaForm.ButtonCrearFrameClick(Sender: TObject);
var
  vFrame: TTPersonaFrame;
begin
  vFrame        := TTPersonaFrame.Create(Self);
  vFrame.Name  := 'nombre_del_frame';
  vFrame.Parent := PanelParaFrame;
  vFrame.Align  := alClient;
end;
</pre>


Y en el código lo veríamos:
El procedimiento se llama '''ButtonCrearFrameClick''' y el argumento '''(Sender: TObject)''' identifica a quién gatilla el evento, en este caso será el mismo botón ya que se va a accionar cuando lo piquemos.
 
En la sección '''var''' de propiedades locales (al procedimiento):
<pre>
<pre>
type
var
   TTPersonaForm = class(TForm)
   vFrame: TTPersonaFrame;
    PanelDeArriba: TPanel;
    Bevel1: TBevel;
    PanelDeAbajo: TPanel;
    Memo1: TMemo;
    procedure FormShow(Sender: TObject);
    procedure FormHide(Sender: TObject);
</pre>
</pre>


Si analizáramos la información adicional del form veríamos que el memo se encuentra indentado dentro del panel de arriba mostrando que el panel lo contiene:
Definimos una variable llamada '''vFrame''' que es de tipo '''TTPersonaFrame''' que es la clase en la que se define el frame, a la que le asignaremos el frame que enseguida crearemos.
 
Luego del '''begin''' podemos escribir el código a ejecutar.
 
Con:
<pre>
<pre>
   object PanelDeArriba: TPanel
   vFrame        := TTPersonaFrame.Create(Self);
    Left = 0
  vFrame.Name  := 'nombre_del_frame';
    Top = 0
    Width = 598
    Height = 338
    Align = alClient
    BevelInner = bvLowered
    BevelOuter = bvNone
    BorderWidth = 7
    Caption = 'PanelDeArriba'
    TabOrder = 0
    object Memo1: TMemo
      Left = 8
      Top = 8
      Width = 582
      Height = 322
      Align = alClient
      BevelOuter = bvNone
      Lines.Strings = (
        'Memo1')
      TabOrder = 0
      ExplicitLeft = 128
      ExplicitTop = 64
      ExplicitWidth = 185
      ExplicitHeight = 89
    end
</pre>
</pre>


=Agregar dos botones=
*Creamos una instancia del frame usando '''TTPersonaFrame.Create(Self);''' y la asignamos a la variable '''vFrame'''.
Ahora podemos agregar dos botones al panel inferior:
*Con '''vFrame.Name''' asignamos un nombre al frame.  
*Uno para (hipotéticamente) guardar el texto ingresado en el memo, lo llamaremos BotonGuardar.
*Otro para cancelar la edición y dejar el panel en blanco, lo llamaremos BotonCancelar.


Vemos como el desarrollador ve los nuevos botones ubicados abajo a la derecha:
Si bien es posible que un componente no tenga un nombre es buena práctica que sí lo tenga.
[[Archivo:20250507 1634 BOTONES EN FORM DESARROLLADOR.png|miniaturadeimagen|no|Botones según la vista del desarrollador:]]


Cuando estamos armando el form en Delphi cada componente tiene acceso a una pantalla llamada '''Object Inspector''' (inspector de objetos) que permite definir sus propiedades como el nombre del control, el caption o texto (por ejemplo, Guardar o Cancelar) y muchas otras.
El nombre debe ser único en la aplicación, si intentáramos crear un componente con un nombre preexistente la aplicación retornaría un error similar a:
[[Archivo:20250508 1215 ERROR NOMBRE COMPONENTE.png|miniaturadeimagen|no|Error al intentar repetir nombre de un componente.]]


Por ejemplo, vemos esa pantalla para el botón de guardar:
El comando:
[[Archivo:20250507 1614 PROPERTY INSPECTOR.png|miniaturadeimagen|no|Inspector de propiedades de un control.]]
<pre>
 
  vFrame.Parent := PanelParaFrame;
La segunda pestaña del inspector de objetos permite definir eventos, por ejemplo, definiremos el evento OnClick que se ejecuta cuando alguien presiona el botón de guardar:
  vFrame.Align  := alClient;
[[Archivo:20250507 1623 PROPERTY INSPECTOR EVENTOS.png|miniaturadeimagen|no|Definiendo eventos en el inspector de objetos.]]
</pre>


Finalmente vemos como los ve el usuario:
*Con '''vFrame.Parent := PanelParaFrame;''' indicamos que el frame estará contenido por ese panel (el que llamamos PanelParaFrame).
[[Archivo:20250507 1636 BOTONES EN FORM USUARIO.png|miniaturadeimagen|no|Botones según la vista del usuario.]]
*Con '''vFrame.Align  := alClient;''' indicamos que el frame debe ocupar todo ese panel.


===Evento OnClick===
La propiedad Align de los controles visuales es muy útil para acomodar los controles en una pantalla claramente legible, sus valores son (en relación con el control que los alberga):
Vemos como quedan definidos los botones y sus eventos OnClick en la interfaz:
*'''alNone''': no definimos alineación.
[[Archivo:20250507 1632 BOTONES EN INTERFAZ FORM.png|miniaturadeimagen|no|Botones en la interfaz del form.]]
*'''alTop''': se alinea hacia arriba.
*'''alBottom''': se alinea hacia abajo.
*'''alLeft''': se alina a izquierda.
*'''alRight''': se alinea a derecha.
*'''alClient''': se alinea hacia arribba y abajo, y hacia la derecha e izquierda ocupando toda el área del '''Parent'''
*'''alCustom''': definida en los márgenes del nuevo control.


La implementación del click sobre el botón de Cancelar es la siguiente:
Finalmente, el '''end''' termina el procedimiento:
<pre>
<pre>
procedure TTPersonaForm.BotonCancelarClick(Sender: TObject);
begin
  { Escribimos el código a ejecutar cuando hagan click sobre el botón de Cancelar
  , por ahora solo limpiamos el contenido del memo y seteamos el cursor sobre
  ese comntrolGuardar... }
  Memo1.Lines.Clear;
  Memo1.SetFocus;
end;
end;
</pre>
</pre>
Recordar que todo lo que está entre '''{''' y '''}''' es un comentario. Fuera de eso la programación hace:
*'''Memo1''' es el nombre del control del memo.
*'''Lines''' es una de sus propiedades para guardar el contenido del memo, es una lista de strings.
*A su vez, esta lista tiene un procedimiento que se llama '''Clear''' para vaciarla y eso vacía el memo.
*Finalmente llama al procedimiento '''SetFocus''' existente en todos los controles visuales que lleva el cursor al memo.

Revisión actual - 20:01 14 may 2025

Introducción

Los frames de Delphi tienen una definición muy similar a la de los forms permitiendo el agregado de controles visuales (y no visuales) y programando su funcionalidad. Pero para mostrarse deben ser 'pegados' en algún otro componente visual, por ejemplo, un panel dentro de un form.

Es decir, que desarrollamos los frames como si fueran un form, pero la única manera de que el usuario interactúe con ellos es pegándolos a un componente que lo permita.

Los frames son útiles para organizar grupos de controles que se usan en múltiples lugares en la aplicación.

Por ejemplo, en Pragma todas las pantallas pueden mostrarse en dentro de la aplicación:

Un frame dentro de la aplicación.

O pueden mostrarse en un form independiente:

Un frame en un form independiente.

En ambos casos es el mismo frame que arma la pantalla (según la definición de la misma en la base de datos, más sobre esto más adelante), y se puede mostrar dentro del panel a derecha de la aplicación o en un form independiente.

(Ver Trabajar con frames en Delphi).

Los frames también permiten la orientación de objetos y un frame puede ser derivado por otro:

  • El frame de base podría contener controles estándar como un menú, un botón de aplicar, un botón de cancelar y funcionalidad básica.
  • Los frames que derivan del anterior pueden agregar controles específicos a los datos que editan, por ejemplo: podría haber una frame de clientes, otro de artículos, con su propia funcionalidad y ambas se favorecen de la funcionalidad del ancestro.

La aplicación de Pragma hace un uso extensivo de los frames.

Frame de ejemplo

Como ayuda para comprender la estructura de los frames crearemos un frame sencillo con algunos controles y funcionalidad básica. Siguiendo con el ejemplo de la clase TPersona el form se llamará TPersonaFrame.

Un frame tiene dos vistas distintas:

  • La vista que ve el usuario durante la ejecucuión de la aplicación.
  • La vista que tiene el desarrollador mientras crea el form.

Crear un nuevo frame

Los frames pueden crearse usando herramientas de Delphi o programando, en este caso usaremos Delphi.

Cuando recién creamos un frame el desarrollador verá lo siguiente:

Frame vacío visto por el desarrollador.

Notar los puntos en pantalla que asisten para ubicar los controles.

Eventualmente veremos la vista del usuario, por ahora vamos a agregar algún control.

Código del nuevo frame

El código hasta ahora apenas si contiene algunos comandos, aunque se nota muy parecido a una clase:

unit PersonaFrame;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs;

type
  TTPersonaFrame = class(TFrame)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

implementation

{$R *.dfm}

end.

Al igual que una clase tiene:

  • unit.
  • interface.
  • uses.
  • type.
  • implementation.

Y deriva de la clase TFrame que es un objeto incluido en Delphi.

Definición de clases en Delphi puede servir como referencia.

Eventos en el frame

Un evento es un acontecimiento que ocurre dentro de una aplicación, los eventos pueden vincularse con procedimientos de objetos para que éstos hagan algo cuando sean notificados.

Al igual que cualquier componente, los frames permiten la definición de eventos. Aunque no tienen, como los forms, los eventos de OnShow y OnHide.

Eventoa en un frame.

(Ver más sobre eventos en Eventos en Delphi).

Agregar controles al frame

Los controles son objetos visuales que permiten la interacción del usuario con la aplicación tales como:

  • Paneles.
  • Cajas de edición.
  • Checkboxes.
  • Botones.

Vamos a agregar algo al frame.

Agregar un checkbox

Un checkbox permite marcar un campo indicando algo, solo tiene 2 valores posibles: marcado o desmarcado.

Para el desarrollador se ve así:

Un checkbox en un frame.

En el código:

type
  TTPersonaFrame = class(TFrame)
    CheckBoxDeAcuerdo: TprxCheckBox;

El tipo del control es TprxCheckBox que es un checkbox programado en Pragma que deriva de TCheckBox.

Delphi además guarda información en un archivo con detalles sobre el tamaño, alineación y jerarquía de los controles del frame, por ejemplo:

object TPersonaFrame: TTPersonaFrame
  Left = 0
  Top = 0
  Width = 345
  Height = 257
  TabOrder = 0
  object CheckBoxDeAcuerdo: TprxCheckBox
    Left = 64
    Top = 56
    Width = 233
    Height = 14
    Caption = 'Click si est'#225' de acuerdo'
    TabOrder = 0
  end
end

Cómo usar el frame

Vamos a mostrar el nuevo frame en el form que creamos en Definición de forms en Delphi, hay que hacer algunos cambios.

Para empezar, vamos a agregar:

  • Un panel justo debajo del memo que albergará el frame llamado PanelParaFrame.
  • Un botón que picaremos para agregar el frame llamado ButtonCrearFrame.

El diseñador verá lo siguiente:

Cambios al form para abrir el frame.

Al botón le agregamos un evento OnClick para que se ejecute cuando lo piquemos, el código es:

procedure TTPersonaForm.ButtonCrearFrameClick(Sender: TObject);
var
  vFrame: TTPersonaFrame;
begin
  vFrame        := TTPersonaFrame.Create(Self);
  vFrame.Name   := 'nombre_del_frame';
  vFrame.Parent := PanelParaFrame;
  vFrame.Align  := alClient;
end;

El procedimiento se llama ButtonCrearFrameClick y el argumento (Sender: TObject) identifica a quién gatilla el evento, en este caso será el mismo botón ya que se va a accionar cuando lo piquemos.

En la sección var de propiedades locales (al procedimiento):

var
  vFrame: TTPersonaFrame;

Definimos una variable llamada vFrame que es de tipo TTPersonaFrame que es la clase en la que se define el frame, a la que le asignaremos el frame que enseguida crearemos.

Luego del begin podemos escribir el código a ejecutar.

Con:

  vFrame        := TTPersonaFrame.Create(Self);
  vFrame.Name   := 'nombre_del_frame';
  • Creamos una instancia del frame usando TTPersonaFrame.Create(Self); y la asignamos a la variable vFrame.
  • Con vFrame.Name asignamos un nombre al frame.

Si bien es posible que un componente no tenga un nombre es buena práctica que sí lo tenga.

El nombre debe ser único en la aplicación, si intentáramos crear un componente con un nombre preexistente la aplicación retornaría un error similar a:

Error al intentar repetir nombre de un componente.

El comando:

  vFrame.Parent := PanelParaFrame;
  vFrame.Align  := alClient;
  • Con vFrame.Parent := PanelParaFrame; indicamos que el frame estará contenido por ese panel (el que llamamos PanelParaFrame).
  • Con vFrame.Align  := alClient; indicamos que el frame debe ocupar todo ese panel.

La propiedad Align de los controles visuales es muy útil para acomodar los controles en una pantalla claramente legible, sus valores son (en relación con el control que los alberga):

  • alNone: no definimos alineación.
  • alTop: se alinea hacia arriba.
  • alBottom: se alinea hacia abajo.
  • alLeft: se alina a izquierda.
  • alRight: se alinea a derecha.
  • alClient: se alinea hacia arribba y abajo, y hacia la derecha e izquierda ocupando toda el área del Parent
  • alCustom: definida en los márgenes del nuevo control.

Finalmente, el end termina el procedimiento:

end;