I'm using Delphi 5 and I'm creating a number of panels at runtime, then creating buttons on the panels, obviously again at runtime. I need to do it this way because I may need to dynamically create more panel/button combinations in the future.
I can do all of this, but I'm at a loss as to how to reference the panels I've created, because I can't find a way to access the panels' component name. Hunting around the Internet I've found that I can use FindComponent to find the panel components by name, but I still don't know how to use that name, because I can't use a string variable to refer to it - e.g. StringVar := Panel.Name. I get a type mismatch, TComponentName versus String.
I created the buttons for each panel as I created the panels. Simplified, it looks like this:
With TypeQuery do begin // Create Panels
First;
While (not eof) do begin // create the actual panel
panelno := FieldByName('Product_type_id').AsInteger;
pnl := Tpanel.Create(Self);
pnl.name := FieldByName('PanelName').AsString;
pnl.color := clInactiveCaption;
pnl.parent := MainForm;
pnl.width := 365;
pnl.Height := 551;
pnl.left := 434
pnl.top := 122;
pnl.caption := '';
With ButtonQuery do begin
Close;
Parameters.parambyname('PanelID').Value := PanelNo;
Open;
First;
While (not eof) and (FieldByName('Product_type_id').AsInteger = PanelNo) do begin //put the buttons on it.
btnName := FieldByName('ButtonName').AsString;
BtnText := FieldByName('ButtonText').AsString;
BtnGroup := FieldByName('Product_Group_ID').AsString;
GrpColour := FieldByName('ButtonColour').AsString;
btn := TColorButton.Create(Self);
btn.Parent := pnl;
btn.Name := BtnName;
Btn.backcolor := HexToTColor(GrpColour);
btn.Font.Name := 'Arial Narrow';
btn.Font.Style := [fsBold];
btn.Font.Size := 10;
. . .
end;
. . .
end;
end;
I've read on several forums (including this one) that there is no way to reference the panels by name directly. I've tried using a component array, but I strike the same problem - I need to refer to the component by its assigned component name.
Okay, I'm not a gun programmer - I've used Delphi for years to create simple programs, but this one is a lot more complex. I've never worked with runtime component creation before.
Can I use FindComponent to make the panels visible or invisible? If so, given what I have shown you above, can you give me the approach I should take in baby-steps?
Thanks in advance ...
I'm not sure what you mean by: "I can't use a string variable to refer to it - e.g. StringVar := Panel.Name."
Try this:
procedure TForm1.FormCreate(Sender: TObject);
var
p: TPanel;
begin
p := TPanel.Create(Self); // create a TPanel at run-time
p.Name := 'MyPanel'; // set a unique name
p.Parent := Self;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
p: TPanel;
StringVar: string;
begin
p := FindComponent('MyPanel') as TPanel;
if Assigned(p) then // p has reference to MyPanel
begin
// use that reference
p.Caption := 'Foo';
StringVar := p.Name;
ShowMessage(StringVar);
end;
end;
Or did I miss anything?
You're conflating the component name with the variable name. The Delphi IDE strives to keep those two the same, for IDE-created components, but they're not necessarily equal. You don't have variable names because you're creating the components dynamically, and you don't know how many variables you'd need. However, you still have control over the component names: Simply assign the Name
property of the component, and then you can use it the same way you use any other component names, by calling FindComponent
. Just make sure the names are unique for each panel instance.
Remember also that the way to deal with variables, when you don't know at compile time how many you'll need, is to use arrays or lists. You can use plain old arrays, or you can use a more sophisticated data structure like TComponentList
or TDictionary
.
Finally, to make it easier to refer to the controls on the panels you're creating, you can dispense with the panels and use frames instead. You can visually design a TFrame
in the IDE and give names to the buttons, and at run time, you can instantiate the frame class, and it will automatically create all the buttons for you, just like when you instantiate a form or data module. You only need to give a name to the new frame object, but that object will already have named fields referring to the buttons.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With