假设我有一个主要表格。主窗体包含两个按钮(打开和关闭),单击每个按钮会创建一个框架,主窗体作为父/所有者。 该框架包含3个按钮(添加,编辑和删除),下面的示例代码为:
框架代码:
unit UntFrame;
...
type
TFmeMain = class(TFrame)
procedure AddClick(Sender: TObject);
procedure EditClick(Sender: TObject);
procedure DeleteClick(Sender: TObject);
private ...
public ...
end;
implementation
{$R *.dfm}
uses ...
procedure TFmeMain.AddClick(Sender: TObject);
begin
AddBtnClick;
end;
procedure TFmeMain.EditClick(Sender: TObject);
begin
EditBtnClick;
end;
procedure TFmeMain.DeleteClick(Sender: TObject);
begin
DelBtnClick;
end;
end.
框架使用的3种方法( AddBtnClick , EditBtnClick 和 DelBtnClick )存在于两个不同的单元,即UntOpen和UntClose但是做了一些事情取决于创建的框架。单击打开按钮时框架应使用UntOpen,当从主菜单中单击关闭按钮时,UntClose适用。
UntOpen代码:
unit UntOpen;
...
procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;
implementation
procedure AddBtnClick;
begin
ShowMessage('add open');
end;
procedure EditBtnClick;
begin
ShowMessage('edit open');
end;
procedure DelBtnClick;
begin
ShowMessage('delete open');
end;
end.
UntClose代码:
unit UntClose;
...
procedure AddBtnClick;
procedure EditBtnClick;
procedure DelBtnClick;
implementation
procedure AddBtnClick;
begin
ShowMessage('add close');
end;
procedure EditBtnClick;
begin
ShowMessage('edit close');
end;
procedure DelBtnClick;
begin
ShowMessage('delete close');
end;
end.
我希望每次创建一个动态单元(如果可能的话)添加到frames的uses子句中,以便单击框架的添加,编辑或删除按钮激发正确的方法(如果打开则从UntOpen中获取方法)如果单击“关闭”按钮,则单击按钮或从UntClose中获取方法。
或者有更有效的方法吗?
感谢。
答案 0 :(得分:5)
您无法动态使用单位; uses子句不能在运行时操作。您似乎想要更改单位列表,以便您的框架代码(已调用AddBtnClick
)将从一个单元或另一个单元中神奇地选择该功能。
Delphi没有这样的方式。如果真的想要类似的东西,请尝试使用Python。
Delphi单元是一个编译时构造。它们无法在运行时进行操作。在编译时,编译器会看到您对AddBtnClick
的调用,然后根据您已使用的单位结算 - 绑定 - 名称。你以后不能再重新命名。
相反,您可以将参数传递给帧类构造函数。将按钮功能放入数据结构中,然后将这些对象传递给框架。 (这也称为依赖注入。)例如,您可以从这个抽象类开始:
type
TButtonBehavior = class
class procedure AddBtnClick; virtual; abstract;
class procedure EditBtnClick; virtual; abstract;
class procedure DelBtnClick; virtual; abstract;
end;
然后,定义您的框架以接收该类的后代,并根据该值编写您的按钮处理程序:
type
TButtonBehaviorClass = class of TButtonBehavior;
TMainFrame = class(TFrame)
private
FBehavior: TButtonBehaviorClass;
...
constructor TMainFrame.Create(AOwner: TComponent; ABehavior: TButtonBehaviorClass);
begin
inherited Create(AOwner);
FBehavior := ABehavior;
end;
procedure TMainFrame.AddBtnClick(Sender: TObject);
begin
FBehavior.AddBtnClick;
end;
接下来,为您希望框架支持的每组行为定义抽象类的后代。如果需要,您可以在不同的单元中定义它们,但由于它们已经在单独的类中,因此不需要进一步分离。
type
TOpenBehavior = class(TButtonBehavior)
class procedure AddBtnClick; override;
class procedure EditBtnClick; override;
class procedure DelBtnClick; override;
end;
TCloseBehavior = class(TButtonBehavior)
class procedure AddBtnClick; override;
class procedure EditBtnClick; override;
class procedure DelBtnClick; override;
end;
最后,在创建框架的新实例时,将其中一个类传递给框架构造函数。
Frame := TMainFrame.Create(Self, TOpenBehavior);
答案 1 :(得分:0)
尝试更像这样的东西:
unit UntFrame;
...
type
TFmeMain = class(TFrame)
procedure AddClick(Sender: TObject);
procedure EditClick(Sender: TObject);
procedure DeleteClick(Sender: TObject);
public
OnAdd: procedure;
OnEdit: procedure;
OnDelete: procedure;
end;
implementation
{$R *.dfm}
procedure TFmeMain.AddClick(Sender: TObject);
begin
if Assigned(OnAdd) then OnAdd;
end;
procedure TFmeMain.EditClick(Sender: TObject);
begin
if Assigned(OnEdit) then OnEdit;
end;
procedure TFmeMain.DeleteClick(Sender: TObject);
begin
if Assigned(OnDelete) then OnDelete;
end;
end.
unit MainForm;
...
uses
..., UntFrame, UntOpen, UntClose;
...
procedure TFormMain.OpenClick(Sender: TObject);
begin
with TFmeMain.Create(Self) do
begin
Parent := ...;
OnAdd := Addr(UntOpen.AddBtnClick);
OnEdit := Addr(UntOpen.EditBtnClick);
OnDelete := Addr(UntOpen.DelBtnClick);
end;
end;
procedure TFormMain.CloseClick(Sender: TObject);
begin
with TFmeMain.Create(Self) do
begin
Parent := ...;
OnAdd := Addr(UntClose.AddBtnClick);
OnEdit := Addr(UntClose.EditBtnClick);
OnDelete := Addr(UntClose.DelBtnClick);
end;
end;
end.
答案 2 :(得分:0)
如果我是你,我会尝试这个解决方案:
主框架:
unit UntFrame;
...
uses
UntOpen, UntClose, ...;
type
TSelectedPage = (spOpen, spClose);
TFmeMain = class(TFrame)
procedure AddClick(Sender: TObject);
procedure EditClick(Sender: TObject);
procedure DeleteClick(Sender: TObject);
private
FSelectedPage: TSelectedPage;
...
public ...
end;
implementation
{$R *.dfm}
uses ...
procedure TFmeMain.AddClick(Sender: TObject);
begin
case FSelectedPage of:
spOpen: TUntOpen.AddBtnClick;
spClose: TUntClose.AddBtnClick;
end;
end;
procedure TFmeMain.EditClick(Sender: TObject);
begin
case FSelectedPage of:
spOpen: TUntOpen.EditBtnClick;
spClose: TUntClose.EditBtnClick;
end;
end;
procedure TFmeMain.DeleteClick(Sender: TObject);
begin
case FSelectedPage of:
spOpen: TUntOpen.DelBtnClick;
spClose: TUntClose.DelBtnClick;
end;
end;
end.
打开单位:
unit UntOpen;
...
type
TUntOpen = class
public
class procedure AddBtnClick;
class procedure EditBtnClick;
class procedure DelBtnClick;
end;
implementation
class procedure TUntOpen.AddBtnClick;
begin
ShowMessage('add open');
end;
class procedure TUntOpen.EditBtnClick;
begin
ShowMessage('edit open');
end;
class procedure TUntOpen.DelBtnClick;
begin
ShowMessage('delete open');
end;
end.
关闭单位:
unit UntClose;
...
type
TUntClose = class
public
class procedure AddBtnClick;
class procedure EditBtnClick;
class procedure DelBtnClick;
end;
implementation
class procedure TUntClose.AddBtnClick;
begin
ShowMessage('add close');
end;
class procedure TUntClose.EditBtnClick;
begin
ShowMessage('edit close');
end;
class procedure TUntClose.DelBtnClick;
begin
ShowMessage('delete close');
end;
end.
这是 OOP 的方式来实现您想要实现的目标,并且在Delphi中 是可能的。