How to free up dynamically created frames?

3.6k views Asked by At

In Delphi 2010... I have a form. On the left side of the form is a Treeview. It shows a multi-level hierarchy. Assume 5 different types of data, Type A, B, C, D and E. On the right side of the form, I have a panel in which I will create a TFrame. If I click in my Treeview on a data element of type 'A', I create a TFrame on the right side of the form which shows tFrame 'A'. Basically I am showing details of the various hierarchies of my TreeView. Each of the 5 types of data uses a different type of TFrame. While I can dynamically create the TFrames, I am having difficulty in knowing WHERE and HOW to delete/free the TFrames?

Do I create a variable which shows the TYPE of the previous TFrame? What is the PROPER way to delete a TFrame? Is it with TFrame.Free? Keep in mind I may need something like Create Frame A, Free Frame A, Create Frame B, Free Frame B, Create Frame A (again), etc...

I have tried something along the lines of...

if Assigned (TFrameA), then TFrameA.free; 

While this appears to work, this causes weird behavior (it caused a button to disappear). It also means that I need to define all 5 types of TFrames as Global Variables.

Any and all thoughts appreciated.

Thanks,

GS

2

There are 2 answers

1
Remy Lebeau On BEST ANSWER

Keep a TFrame variable so you know what the currently displayed frame is. When you display a different frame, you can free/cache the current frame first.

If you want to cache frames, then keep five separate TFrame variables, one for each page type. When you need to show a page, create it only if you have not already done so:

private
  CurrentFrame: TFrame;
  Frames: array[0..4] of TFrame;

procedure TMyForm.TreeView1Change(Sender: TObject);
begin
  if CurrentFrame <> nil then
  begin
    CurrentFrame.Parent := nil;
    CurrentFrame := nil;
  end;

  if Frames[OneOfTheIndexes] = nil then
    Frames[OneOfTheIndexes] := TAppropriateFrameType.Create(Self);

  Frames[OneOfTheIndexes].Parent := Panel1;
  CurrentFrame := Frames[OneOfTheIndexes];
end;

If you want to recreate frames instead, then simply remove the array and Free() the current frame before displaying a new one:

private
  CurrentFrame: TFrame;

procedure TMyForm.TreeView1Change(Sender: TObject);
begin
  if CurrentFrame <> nil then
    FreeAndNil(CurrentFrame);

  CurrentFrame := TAppropriateFrameType.Create(Self);
  CurrentFrame.Parent := Panel1;
end;
0
afrazier On

Depending on your UI and data setup, you only need to keep a reference to the active frame in your form and free that before creating a new one.

Destructors are dynamic, so you don't need to keep track of what kind of frame you have before freeing it, though other considerations may require you to check the class type with the is or as keywords.