Search code examples
delphivcl

How to set dynamic panel as component's parent?


well, I am creating at runtime a TImage and a Tlabel, I want those two to be child of a Tpanel, which I also create at runtime. here is some code:

with TPanel.Create(FlowPanelPlantillas) do
begin
  Name := 'Panel'+Query.FieldByName('ID').AsString;
  //Etc Etc
end;

and the image

with TImage.Create(TWinControl(FindComponent('Panel'+Query.FieldByName('ID').AsString))) do
  begin
    Name:= 'P'+Query.FieldByName('ID').AsString;
    Parent := TWinControl(FindComponent('Panel'+Query.FieldByName('ID').AsString));        
  end;

that is what I am doing but I doesn’t work, the panel is created and viewed properly but the image doesn’t appear in the panel, it is empty.

I am using Delphi Rio VCL

I appreciate any help.


Solution

  • A with statement does not provide you access to the object that is being referenced. You need that reference in order to assign it to something, like a Parent property. You should save the reference to a variable first.

    Also, don't forget to set the Visible property, too.

    Try this:

    var
      Panel: TPanel;
    
    Panel := TPanel.Create(FlowPanelPlantillas);
    with Panel do
    begin
      Name := 'Panel'+Query.FieldByName('ID').AsString;
      //Etc Etcl
      Visible := True;
    end;
    
    ...
    
    Panel := TWinControl(FindComponent('Panel'+Query.FieldByName('ID').AsString));
    // or, just use the same variable already assigned
    // previously, if it is still in scope...
    
    with TImage.Create(Panel) do
    begin
      Name:= 'P'+Query.FieldByName('ID').AsString;
      Parent := Panel;
      Visible := True;
    end;
    

    There is really very little use for FindComponent() and named objects in properly designed dynamic code. The naming system is primarily meant for DFM streaming only.

    For that matter, once you have a variable with an object reference in it, there is very little use for with, either:

    var
      Panel: TPanel;
      Image: TImage;
    
    Panel := TPanel.Create(FlowPanelPlantillas);
    Panel.Name := 'Panel'+Query.FieldByName('ID').AsString;
    //Etc Etcl
    Panel.Visible := True;
    
    ...
    
    Panel := TWinControl(FindComponent('Panel'+Query.FieldByName('ID').AsString));
    // or, just use the same variable already assigned
    // previously, if it is still in scope...
    
    Image := TImage.Create(Panel);
    Image.Name := 'P'+Query.FieldByName('ID').AsString;
    Image.Parent := Panel;
    Image.Visible := True;
    

    Using variables to hold the object references also helps with debugging, so you can make sure your variables are actually receiving the values you are expecting. You don't get that option when using with.