WartH0g
WartH0g

Reputation: 35

How do you add an item to a TStackPanel at runtime

I have a TStackPanel which I want to add a number of frames into at runtime. The number may vary each time the form is opened.

There seems to be limited information about TStackPanel around, and the examples I can find are in languages other than Delphi.

I have a loop that creates the frame, gives it a unique name and then adds it to the TStackPanel:

for i := 0 to 10 do
  begin
    mfSubFrame[i] := TMyFrame.Create(Application);
    mfSubFrame.Name := name_array[i];
    StackPanel1.InsertComponent(mfSubFrame[i]);
  end;

This does not put anything in the stack panel. If I change the SP line to:

StackPanel1.InsertControl(mfSubFrame[i]); 

then I do get a frame in the SP. It is the last one of the loop as I can tell by the name, the others may be hidden behind it but I can't tell. They are certainly not stacked horizontally like they should.

I have tried various other things like setting the parent of the frames to be the SP, and had a look at things like:

StackPanel1.Components.InsertComponent(mfSubFrame[i]); 

and other sub-methods, but had no luck so far.

I suspect it may require a combination of statements, like add a control item as well as the actual component, but as I am working on the basis of trial and error it could be a long time before I stumble on the right combination.

Upvotes: 1

Views: 1139

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 598279

InsertComponent() changes a component's Owner, which has no effect on visual display. You are creating each frame with Application as its Owner, and then changing its Owner to StackPanel1. You should assign the desired Owner when calling the component's constructor.

InsertControl() changes a control's Parent, which does affect visual display. You are creating each frame without a Parent, and then changing its Parent to be StackPanel1. You should be using the actual Parent property, not calling InsertControl() directly.

That being said, TStackPanel has a ControlCollection property that you are not doing anything with. That collection manages the actual stacking.

If needed 1, for each frame, try calling StackPanel1.ControlCollection.Add(), and then assigning the frame to the TStackPanelCollectionItem.Control property.

1: I don't have the source code for TStackPanel to look at, but I suspect TStackPanel probably handles this automatically for UI controls dropped onto it at design-time, but you might need to perform it manually for controls that you create dynamically at runtime. I'm not sure.

Upvotes: 2

Andreas Rejbrand
Andreas Rejbrand

Reputation: 109148

I have never used the TStackPanel before, but it seems like you can add controls to it exactly the same way you add controls to any other windowed control: just create the control and assign its Parent.

For example,

for var i := 1 to 10 do
begin
  var Memo := TMemo.Create(Self);
  Memo.Parent := StackPanel1;
end;

will add ten memo controls (all owned by Self) to StackPanel1. There is no need to name the controls; referring to components by string name at runtime is an antipattern. (So is using FindComponent.)

Upvotes: 2

Related Questions