如何在Delphi中将TPageControl选项卡分离成单独的文件?

8

我有一个VCL表单,上面有一个包含五个选项卡的TPageControl。每个TTabSheet的内容都不太相关,且有很多独立的控件和处理逻辑...因此,我想将其分解为更容易处理“仅限于该选项卡”代码的形式。可以使用以下代码:

//-------------------------- begin rules tab methods -------------------

现在已经不适用了。实际上,我希望每个标签都在单独的文件中。

目前,我正在考虑为每个TTabPage创建一个VCL框架。如果我这样做,我需要在构造函数中加载所有框架到TPageControl中,或者当选项卡显示时加载。

这是一个好方法吗?是否更好地为每个选项卡制作整个TForm?我应该继续将选项卡包装在TPageControl中,还是如果内容动态加载,则应将其更改为TTabControl?如果这是一个好方法,那么是在启动时加载所有选项卡更好,还是每次显示选项卡时加载更好?(如果在大多数/所有情况下不是完全明显哪个更好,则可能需要列出利弊)


4
下投票的人,我真的希望您留下评论以解释为什么这是一个糟糕的问题,这样我就可以改进它或下次提出更好的问题。 - Jessica Brown
2
你的问题太过宽泛和基于个人观点,我认为。你在这里提出了至少5个不同的问题,其中四个在项目符号中,第五个是“最佳方式”问题,如果没有实际源代码的访问权限(和分析时间),是无法回答的,“最佳方式”即使可能也是一个主观看法。 - Ken White
1
除了 TFrame 的建议之外,你还可以为不同的模块编写单独的 include 文件,或将选项卡页转换为窗体并在启动时将其停靠在你的页面控件容器中。 - Free Consulting
1
@FreeConsulting 看看我的回答吧 ;o) - Sir Rufo
1
@SirRufo,噢,也许我需要一副新眼镜 :-) - Free Consulting
显示剩余3条评论
2个回答

8

您可以使用Frames或Forms。

  • 对于Frames,您需要为每个Frame添加一个TabControl作为父控件。
  • 对于Forms,您需要将每个Form手动停靠到PageControl上(Form的标题将自动成为TabControl的标题)。

procedure TMyForm.AddPage( AFormClass : TFormClass );
var
  LForm : TForm;
begin
  LForm := AFormClass.Create( Self );
  LForm.ManualDock( PageControl1, nil, alClient );
  LForm.Show;
end;

例子

创建一个基本的设置表单

unit UI_Form_SettingBase;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TUISettingBase_Form = class( TForm )
  private

  protected
    procedure DoSaveData; virtual;
  public
    function CanSaveData : Boolean; virtual;
    procedure SaveData;
  end;

  TUISettingBase_FormClass = class of TUISettingBase_Form;

var
  UISettingBase_Form : TUISettingBase_Form;

implementation

{$R *.dfm}
{ TUISettingBase_Form }

function TUISettingBase_Form.CanSaveData : Boolean;
begin
  Result := True;
end;

procedure TUISettingBase_Form.DoSaveData;
begin

end;

procedure TUISettingBase_Form.SaveData;
begin
  if CanSaveData
  then
    DoSaveData;
end;

end.

将所有设置表单从该表单派生,并覆盖DoSaveData和可选地覆盖CanSaveData方法。

常见设置(使用简单的复选框)

unit UI_Form_SettingCommon;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, UI_Form_SettingBase, Vcl.StdCtrls;

type
  TUISettingCommon_Form = class(TUISettingBase_Form)
    CheckBox1: TCheckBox;
  private

  protected
    procedure DoSaveData; override;
  public

  end;

var
  UISettingCommon_Form: TUISettingCommon_Form;

implementation

{$R *.dfm}

procedure TUISettingCommon_Form.DoSaveData;
begin
  inherited;
  // code to save the data
end;

end.

连接设置 (使用简单的编辑控件)

unit UI_Form_SettingConnection;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, UI_Form_SettingBase, Vcl.StdCtrls;

type
  TUISettingConnection_Form = class( TUISettingBase_Form )
    Edit1 : TEdit;
  private
  protected
    procedure DoSaveData; override;
  public
  end;

var
  UISettingConnection_Form : TUISettingConnection_Form;

implementation

{$R *.dfm}
{ TUISettingConnection_Form }

procedure TUISettingConnection_Form.DoSaveData;
begin
  inherited;
  // code to save the data
end;

end.

组合在一起:真正的设置表单

主要的设置表单也是从SettingBase派生而来

unit UI_Form_Settings;

interface

uses
  System.Generics.Collections,
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, UI_Form_SettingBase, Vcl.StdCtrls,
  Vcl.ExtCtrls, Vcl.ComCtrls;

type
  TUISettings_Form = class( TUISettingBase_Form )
    PageControl1 : TPageControl;
    Panel1 : TPanel;
    Save_Button : TButton;
  private
    FForms : TList<TUISettingBase_Form>;
    procedure AddSettingPage( ASettingFormClass : TUISettingBase_FormClass );
  protected
    procedure DoSaveData; override;
  public
    function CanSaveData : Boolean; override;
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
  end;

var
  UISettings_Form : TUISettings_Form;

implementation

{$R *.dfm}

uses
  UI_Form_SettingCommon, UI_Form_SettingConnection;
{ TUISettings_Form }

procedure TUISettings_Form.AddSettingPage( ASettingFormClass : TUISettingBase_FormClass );
var
  LForm : TUISettingBase_Form;
begin
  LForm := ASettingFormClass.Create( Self );
  try
    LForm.ManualDock( PageControl1, nil, alClient );
    LForm.Show;
    FForms.Add( LForm );
    LForm := nil;
  finally
    LForm.Free;
  end;
end;

procedure TUISettings_Form.AfterConstruction;
begin
  inherited;
  FForms := TList<TUISettingBase_Form>.Create;
  // add all the setting forms
  AddSettingPage( TUISettingCommon_Form );
  AddSettingPage( TUISettingConnection_Form );
end;

procedure TUISettings_Form.BeforeDestruction;
begin
  inherited;
  FForms.Free;
end;

function TUISettings_Form.CanSaveData : Boolean;
var
  LForm : TUISettingBase_Form;
begin
  // iterate all setting forms if they can save the data
  Result := True;
  for LForm in FForms do
    Result := Result and LForm.CanSaveData;
end;

procedure TUISettings_Form.DoSaveData;
var
  LForm : TUISettingBase_Form;
begin
  inherited;
  // iterate all setting forms and save the data
  for LForm in FForms do
    LForm.SaveData;
end;

end.

显然你不能将ActionManagers添加到框架中,只能添加到表单中。因此,在这种情况下问题基本上已经解决。感谢您提到了这两种解决方案。 - Jessica Brown

8
我想做的事情(这个问题的重点)是如何分解包含五个TTabSheet的TPageControl。每个选项卡表现为UI的一个相对独立的部分(以及相应的处理逻辑),因此将每个选项卡分成单独的文件会很好。
您可以使用TFrame来实现。为每个页面提供自己的Frame,在其自己的文件中实现和设计它们,并拥有自己的DFMs。
对于每个被分解的选项卡,我是否需要添加新的VCL表单?还是VCL帧?
使用帧。不要使用嵌入式表单,它们不太好用。帧是为此目的而设计的。
如果每个选项卡的内容都从面板加载,我应该保留TPageControl还是改为TTabControl?
在创建新框架并根据需要进行设计后,您可以执行以下操作之一:
1. 将框架放置在组件面板上(右键单击设计器中的框架,然后选择“添加到面板”),然后可以在设计时将其拖放到所需的TTabSheet上。如果要使框架填充整个TTabSheet,请设置框架的Align属性为alClient。
2. 在运行时实例化框架对象,然后将其父级属性设置为所需的TTabSheet。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接