Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TTabSet vs. TTabControl vs. TPageCtrl/TTabSheet?

I was wondering why Delphi (2007) provides three widgets that seem to do the same thing, and what the advantages/disadvantages are for each.

On the same topic, if I want to display different sets of controls, why should I favor eg. PageControl + TabSheets + Frames, instead of just displaying different frames directly on the parent form?

Thank you.

like image 212
Gulbahar Avatar asked Aug 17 '09 15:08

Gulbahar


2 Answers

From the helpfile on TTabSet:

Tab set controls are commonly used to display tabbed pages within a dialog box. TTabSet is provided for backward compatibility. Use TTabControl component in 32-bit Windows applications.

So the real question is, what's the difference between TTabControl and TPageControl? The difference is that TTabControl only has one "page", whereas TPageControl has one page for each tab. This makes them useful in different situations.

TPageControl is useful for dialogs where you want to fit more UI on the screen than you have screen space to fit it in. Organize your UI into categories and put each category on one page. You see this pattern a lot in Options dialogs, for example.

TTabControl, on the other hand, works well for working on an array/list of objects. Create a UI to display and edit the properties of a single object, and place it on a TTabControl, then create one tab for each object and set up the event handlers so it'll load a new object from the array into the controls whenever you change tabs.

As for the frames question, the main reason to use a TPageControl in conjunction with frames is because it provides a prebuilt way to decide which frame to display. That way you don't have to reinvent a mechanism for it.

like image 103
Mason Wheeler Avatar answered Nov 16 '22 00:11

Mason Wheeler


One method that I have used with great success is to use frames with a TPageControl and late bind my frames to the tPageControl the first time the page is selected. This keeps the form load time down, by not creating frames which are never viewed, but yet allows the flexibility of being created, the state is maintained when changing between tabs. Recently I switched to using forms and embedding them instead of frames...but the concept is the same.

The same can be done using a single "mount point" on a TTabControl and switching it out as the tab is changed, but then the issue of how to deal with the tab state as tabs are switched back too comes up.

[EDIT] The question comes up how do I handle communication between the frame and the parent form. This actually is very easy to do using interfaces. Just create a new unit that will be shared by the form AND the frame and add two interfaces:

type
  IFormInterface = interface
    [guid]
    procedure FormProc;
  end;

  IFrameInterface = interface
    [guid]
    procedure SetFormController(Intf:IFormInterface);
  end;

Have the form implement the IFormInterface, and the frame implement the IFrameInterface. When you click on a tab and show a frame, then run code like the following:

var
  FrameIntf : IFrameInterface;
begin
  if Supports(FrameObj,IFrameINterface,FrameIntf) then
    FrameIntf.SetFormController(Self);
end;  

your frame implementation of the SetFormController method would then hold onto the reference passed, which would allow it to call upwards into the form.

procedure TFrame1.SetFormController(Intf:IFormInterface);
begin
  fFormController := Intf;
end;

Procedure TFrame1.Destroy; override;
begin
  fFormController := nil;  // release the reference
  inherited;
end;

Procedure TFrame1.Button1Click(Sender:tObject);
begin
  if fFormController <> nil then
    fFormController.FormProc
  else
    Raise Exception.Create('Form controller not set');
end;
like image 37
skamradt Avatar answered Nov 16 '22 00:11

skamradt