2011-12-17 10 views
8

tengo un pequeño problema. Intento crear en Delphi7 una lista de componentes en tiempo de ejecución y cambiarles el tamaño con el evento .OnResize del formulario pero sin uso ... no puedo encontrar la manera de hacerlo.¿Cómo me refiero a los componentes creados en tiempo de ejecución en lugar de hacerlo en el diseñador de formularios?

Aquí está mi código:

procedure TForm1.Button1Click(Sender: TObject); 
var 
    //ExtCtrls 
    panel: TPanel; 
    memo: TMemo; 
    splitter: TSplitter; 
    list: TListBox; 
begin 
    panel := TPanel.Create(Self); 
    list := TListBox.Create(Self); 
    splitter := TSplitter.Create(Self); 
    memo := TMemo.Create(Self); 

    with panel do 
    begin 
    Parent := Form1; 
    BevelOuter := bvNone; 
    Top := 12; 
    Left := 12; 
    Height := Form1.Clientheight - 24; 
    Width := Form1.Clientwidth - 24; 
    end; 

    with list do 
    begin 
    Parent := panel; 
    Align := alClient; 
    Top := 0; 
    Height := panel.Height; 
    end; 

    with splitter do 
    begin 
    Parent := panel; 
    Top := 0; 
    Width := 12; 
    Align := alLeft; 
    end; 

    with memo do 
    begin 
    Parent := panel; 
    Top := 0; 
    Left := 0; 
    Width := round(panel.Width/4) * 3; 
    Height := panel.Height; 
    Align := alLeft; 
    end; 
end; 

¿Tengo que registrar sus nombres de alguna manera con el fin de utilizarlos en el evento del formulario? O tal vez, para crear una clase e incluirlos?

¡Cualquier tipo de ayuda es realmente apreciada! Gracias de antemano.

Respuesta

9

Las variables son locales para el procedimiento donde se crean, por lo que no puede hacer referencia a ellas utilizando esas variables cuando se encuentre fuera de ese procedimiento. La solución es convertirlos en campos de la clase de formulario.

type 
    TForm1 = class(TForm) 
    procedure FormResize(Sender: TObject); 
    procedure Button1Click(Sender: TObject); 
    private 
    FPanel: TPanel; 
    FMemo: TMemo; 
    FSplitter: TSplitter; 
    FList: TListBox; 
    end; 

A continuación, el controlador de eventos FormResize puede referirse a ellos.

procedure TForm1.FormResize(Sender: TObject); 
begin 
    if Assigned(FPanel) then 
    begin 
    ... 
    end; 
end; 

No se olvide de eliminar las variables locales de Button1Click y el uso de los campos en su lugar.

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    FPanel := TPanel.Create(Self); 
    ... 
end; 
+0

Eso hizo el truco David. Ahora solo tendré que estudiar cómo esto puede afectar algunas otras cosas como, una serie de paneles, etc. ¡Muchas gracias! –

+0

@DimitrisNats Las matrices de controles se manejan de manera similar. Solo necesita un campo de su clase del tipo apropiado, p. 'FPanels: array de TPanel'. –

4

Aunque la respuesta de David es también muy correcta, pensé que iba a tomar un momento y entrar en algo más de detalle. Por lo que parece, pareces ser muy nuevo con Delphi. Hay un problema muy común con los principiantes, que David no aborda en su respuesta, relacionado con la creación y liberación de estos objetos. Cada vez que llamas "Crear" en una clase, en algún momento, cuando termines, tienes que 'Liberar' esa clase. Si no se libera nada, se producirá una pérdida de memoria y nadie lo quiere. La liberación es tan simple como la creación, hasta que entra en el tema de mantener una lista de objetos (que no necesita en este momento).

Digamos que desea crear un control de cuadro de texto (TEdit) y colocarlo en el centro de su formulario. Ahora, antes que nada, Delphi IDE le permite simplemente dejar caer estos controles en su forma, solo asegúrese de saber. No necesariamente necesita crear/liberar usted mismo, a menos que haya algún escenario especial. Pero hacer esto es peligroso. Por el bien de este ejemplo, asumimos que este control TEdit estará allí durante toda la duración de su aplicación.

Primero, necesita declarar una variable en alguna parte para este control. El lugar más razonable para esto es dentro de la clase donde se utilizará (en este caso, su formulario al que llamaremos Form1). Cuando trabaje con variables (aka Fields) en su formulario, asegúrese de no colocar nada sobre la sección private. Todo lo que está por encima de private está destinado a código generado automáticamente por Delphi para cualquier cosa que se haya eliminado (y sea visual) en su forma. De lo contrario, cualquier cosa creada manualmente debe pasar por private o por debajo de public. El área public sería un buen lugar para su control de ...

type 
    TForm1 = class(TForm) 
    private 

    public 
    MyEdit: TEdit; 
    end; 

Ahora que se ha declarado, tenemos que crear (y gratis) de ella. Es una buena práctica que cada vez que crees algo, que coloques inmediatamente el código para liberarlo antes de continuar trabajando. Cree un controlador de eventos para los eventos OnCreate y OnDestroy de su formulario ...

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    MyEdit:= TMyEdit.Create(nil); 
    MyEdit.Parent:= Self; 
    MyEdit.Left:= (ClientWidth div 2) - (Width div 2); 
    MyEdit.Top:= (ClientHeight div 2) - (Height div 2); 
end; 

procedure TForm1.FormDestroy(Sender: TObject); 
begin 
    if assigned(MyEdit) then MyEdit.Free; 
end; 

Si no se crea este objeto (antes de la creación o después de la destrucción), por lo que recibirá una "Violación de acceso" cuando se trata de usarlo. Esto se debe a que su aplicación intenta acceder a un área de la memoria de la computadora que no está asignada o no coincide con el tipo que pretendía obtener.

Bueno, eso es lo básico para arreglar su situación. Sin embargo, una cosa más que mostrarte. Supongamos que solo necesita crear un objeto durante un breve período de tiempo, durante la duración de un procedimiento. Hay un enfoque diferente para esto. En su código anterior, declaró su variable directamente dentro del procedimiento. Este ejemplo muestra que cuando es necesario hacer esto ...

procedure TForm1.Button1Click(Sender: TObject); 
var 
    MyObject: TMyObject; 
begin 
    MyObject:= TMyObject.Create; 
    try 
    MyObject.DoSomething; 
    Caption:= MyObject.GetSomething; 
    finally 
    MyObject.Free; 
    end; 
end; 

Ves, siempre y cuando MyObject solamente se utilizará en esta una llamada a este procedimiento, entonces se puede declarar aquí. Pero si se espera que el objeto permanezca en la memoria una vez terminado este procedimiento, las cosas se vuelven más complicadas. De nuevo, en su caso, quédese con poner esto en la clase del formulario hasta que esté más familiarizado con la creación dinámica de objetos.

Una nota final, como se mencionó anteriormente, usted tiene la capacidad de colocar el control TEdit directamente en su formulario en tiempo de diseño sin escribir su propio código. Si hace esto, debe recordar NO intentar crear o liberar estos. Este es también el caso cuando Delphi colocará automáticamente el código sobre la sección private, es cuando hay algo con lo que no debe jugar.

+0

@downvoter explica por favor lo que hice mal y lo arreglaré. –

+0

Buena información - He votado positivamente. –

+2

@Jerry No soy el que menosprecia, pero creo que lo que se ha perdido es que todos los constructores pasan 'Self' como el parámetro' Owner'. Esto significa que todos estos objetos serán destruidos cuando se destruya la forma. –

2

No creo que soy elegible para "comentar", así que estoy fraseando esto como una "respuesta". Si desea cambiar el tamaño de los componentes de tiempo de ejecución cuando su matriz cambia de tamaño, eche un vistazo a la propiedad Anchors. Puede ahorrarte mucho trabajo.

Cuestiones relacionadas