1

我有一个带有显示 10 个选项卡的 TabControl 的 FMX 应用程序(但在 VCL 中应该相同)。根据应用程序状态和用户权限,选项卡设置为可见或不可见。

它运作良好,但我不喜欢

  • 一切都在一起,并以主要形式混乱

  • 和选项卡内容被初始化,即使它们从未变得可见。

所以我考虑使用在标签可见时创建的框架。

每个框架只能存在一次,并且应该可以轻松地从另一个框架操作一个框架(另一个框架上的访问控制)。

我喜欢优雅的解决方案和简短的代码 :)

这是我已经找到的,非常好,但很旧: 用框架替换 TabSheets - 由 Dan Miser

4

1 回答 1

0

该解决方案对每一帧都有一个全局变量。所有框架都可以在其实现部分使用主窗体单元,并且可以轻松访问其他框架及其所有控件,即使无需将其他框架添加到使用子句。

选项卡开始不可见,并且它们的框架未初始化。TabA.Activate;显示选项卡并设置焦点。TabA.Frame.Label1轻松访问该框架上的控件。TabA.Visible:= False;隐藏选项卡并释放框架。

泛型在这里真的很有帮助,我喜欢它。

非常欢迎提出改进意见...

type
  TFormMain = class(TForm)
    TabControl: TTabControl;
    TabInfo: TTabItem;
    procedure FormCreate(Sender: TObject);
  private
    procedure AddTab<T: TTabItem>(out Tab: T);
  public
    TabA: TTabItemFrame<TFrameA>;
    TabB: TTabItemFrame<TFrameB>;
    TabC: TTabItemFrame<TFrameC>;
  end;

var
  FormMain: TFormMain;

implementation

procedure TFormMain.FormCreate(Sender: TObject);
begin
  AddTab(TabA);
  AddTab(TabB);
  AddTab(TabC);

  TabA.Activate;
end;

procedure TFormMain.AddTab<T>(out Tab: T);
begin
  Tab:= TabControl.Add(T) as T;
end;

---------------------------------------------------------------------
unit _FrameBase;

interface

uses
  System.Classes, FMX.Forms, FMX.TabControl;

type
  TFrameBase = class abstract(TFrame)
  public
    class function GetTitle: string; virtual; abstract;
  end;

  TTabItemFrame<T: TFrameBase> = class(TTabItem)
  private
    FFrame: T;
  protected
    procedure Hide; override;
    procedure Show; override;
  public
    constructor Create(AOwner: TComponent); override;
    function Activate: T;
    property Frame: T read FFrame;
  end;

implementation

{ TTabItemFrame }

constructor TTabItemFrame<T>.Create(AOwner: TComponent);
begin
  inherited;
  Text:= T.GetTitle;
  Visible:= False;
end;

function TTabItemFrame<T>.Activate: T;
begin
  Visible:= True;
  TabControl.ActiveTab:= Self;
  Result:= FFrame;
end;

procedure TTabItemFrame<T>.Hide;
begin
  inherited;
  FFrame.DisposeOf;
  FFrame:= nil;
end;

procedure TTabItemFrame<T>.Show;
begin
  inherited;
  FFrame:= T.Create(Self);
  FFrame.Parent:= Self;
end;

end.

---------------------------------------------------------------------

type
  TFrameA = class(TFrameBase)
    Label1: TLabel;
  public
    class function GetTitle: string; override;
  end;

implementation

// if it's necessary to access components or methods of
// any other frame or the main form directly
uses
  _FormMain;

//...

更新:我决定在我的 FMX 应用程序中使用表单而不是框架,因为框架在设计时不能使用样式。一个副作用是,我可以使用表单标题代替类函数作为选项卡标题。

将表单嵌入到 tabitem 中有点棘手:

constructor TFormTabBase.Create(AOwner: TComponent);
begin
  inherited;
  while ChildrenCount > 0 do Children[0].Parent:= AOwner as TTabItem;
end;

procedure TTabItemForm<T>.Show;
begin
  inherited;
  FFormTab:= T.Create(Self);
  Text:= FFormTab.Caption;
end;
于 2018-02-20T15:33:44.503 回答