这可能看起来有点新手,但我确实遇到了问题。我有一个表单(不是主要表单)从用户那里获取许多不同的数据,我想将它传递给一个管理器类来创建一个带有这些的对象。问题是我不能让这个类使用其他单元(获得循环使用),并且它也无法访问经理类实例(主要形式)。
那么,我该怎么办?我已经考虑过使用公共变量,但我对此感觉不好(关于OOD模式)。
答案 0 :(得分:7)
我的建议是从GUI中分离数据,因为这会导致您的问题。 如果您有一个从用户收集数据的表单,那么您应该将数据与表单区分开来(TForm)。
例如,假设您有一些TForm实例和一个表单,该表单由三个字段构成:用户名,年龄和位置。您希望用户输入这三个内容,但是当用户关闭表单时,您应该将此插入的数据传递到某个对象上。表单关闭,它被释放,但对象仍然存在。然后将此对象传递给经理对象。
简单示例:
这是您保存数据的记录
type
TGatheredData = record
Name: String[40];
Age: Byte;
Location: String[40];
end;
你的TForm1可能有一个aditional构造函数:
constructor TForm1.Create(AOwner: TComponent; var GatheredData: TGatheredData );
begin
inherited Create(AOwner);
FGatheredData := GatheredData;
//you may want to deserialize GatheredData here and show the data in your form controls
end;
你打电话给它,通过GatheredData然后你正在显示你的表格。
接下来,在关闭表单时,从表单控件中选择upd数据。
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if Self.ModalResult = mrOk then
begin
//serialize your object
FGatheredData.Name := '';//name taken from control f.e. TEdit
FGatheredData.Age := '';//name taken from control f.e. TSpinButton
FGatheredData.Location := '';//name taken from control f.e. TEdit
end;
end;
拥有此数据记录后,您现在可以以相同的方式将其传递给Manager对象。 您以这种方式从GUI中分离数据,并且您可以轻松地将记录插入到多种不同的表单中。
请记住在外部单位中声明您的记录类型,并在您的经理单位和表格单位中使用该单位。
希望这有点帮助。
答案 1 :(得分:3)
“经理类”不应该是任何一种形式的单位,而应该是它自己的单位。通过将GUI代码与业务逻辑分离,可以避免类似这样的问题。
答案 2 :(得分:2)
[编辑:我最初将这个答案放在评论中,但决定将其全部解答。 TDatamodules在Delphi中过于重要和过于普遍,不强调它们,它们提供了内置的易于使用的方法来分离逻辑和数据中的gui。]
其他人对gui与逻辑和数据脱钩发表了很好的评论。令人惊讶的是,我认为没有人提到在Delphi中TDatamodules是这样做的主要方法之一。您将数据和逻辑放在Datamodule上,然后让两个表单“使用”Datamodule来访问其数据和方法。以下是简要介绍:http://delphi.about.com/od/database/l/aa101601a.htm
您的两种表单(和其他表单)都可以访问位于Datamodule单元上/内的数据集或其他数据/数据结构。应该有一个易于查找的示例项目,说明了设置,因为它(或者至少是)构建Delphi应用程序的标准方法。
答案 3 :(得分:2)
如果我理解你的问题,那么你希望经理管理表格(而不是访问经理的表格)。对?您无法关闭主窗体,就像关闭应用程序一样,但您可以隐藏它。 (除非您创建一个控制台应用程序)。但它提出了一个很好的小问题:)
所以......启动表格(主表格)是:
。 。
uses
ManagerU;
type
TFormSplash = class(TForm)
procedure FormPaint(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
Manager: TManager;
end;
var
FormSplash: TFormSplash;
implementation
{$R *.dfm}
procedure TFormSplash.FormCreate(Sender: TObject);
begin
Manager := TManager.Create;
end;
procedure TFormSplash.FormDestroy(Sender: TObject);
begin
Manager.Free;
end;
procedure TFormSplash.FormPaint(Sender: TObject);
begin
if Visible then
begin
Manager.GetData(Self);
Hide;
Manager.DoDataStuff;
Close;
end;
end;
end.
DaaObject是:
unit DataObjectU;
interface
uses classes;
type TDataObject = class(TObject)
Data: string;
end;
implementation
end.
经理是:
interface
uses DataObjectU;
type
TManager = Class(Tobject)
MyData: TDataObject;
constructor Create; virtual;
destructor Destroy; override;
procedure GetData(OwnerForm: TForm);
procedure DoDataStuff;
end;
implementation
uses DataFormU;
{ TManager }
constructor TManager.Create;
begin
inherited Create;
MyData := TDataObject.Create;
end;
destructor TManager.Destroy;
begin
MyData.Free;
inherited;
end;
procedure TManager.DoDataStuff;
begin
// do stuff with data here
end;
procedure TManager.GetData(OwnerForm: TForm);
var
MyDataForm: TDataForm;
begin
MyDataForm := TDataForm.Create(OwnerForm);
try
if MyDataForm.ShowModal = mrOK then
begin
MyData.Data := MyDataForm.Data;
end;
finally
MyDataForm.Free;
end;
end;
end.
数据形式是:
type
TDataForm = class(TForm)
btnOK: TButton;
procedure btnOKClick(Sender: TObject);
private
function GetData: String;
{ Private declarations }
public
{ Public declarations }
MyData: TDataObject;
property Data: String read GetData;
end;
var
DataForm: TDataForm;
implementation
{$R *.dfm}
procedure TDataForm.btnOKClick(Sender: TObject);
begin
MyData := TDataObject.Create;
ModalResult := mrOk;
end;
function TDataForm.GetData: String;
begin
Result := MyData.Data;
end;
你需要填写其余的单位代码并释放一些东西,但基本上是这样的:
启动程序(创建启动)
Splash创建管理器调用它以从dataform获取数据然后隐藏自己
调用manager来管理数据
当经理完成时,然后关闭。
除非通过任务管理器,否则没有其他方法可以将其关闭!)
添
答案 4 :(得分:1)
要解决循环引用错误,请在实现部分中使用该单元。
implementation
{$R *.DFM}
Uses <Your Unit>;
end.
答案 5 :(得分:0)
拥有这3个单位: FormMain FormEdit UnitMyClass
您在FormMain中创建对象,并在以下函数中将其传递给FormEdit:
class function FormEdit.EditMyObject(AObject: TMyClass): boolean;
这个函数将showModal表格。表单将对对象进行更改,如果用户按下OK,则返回True。
正如您在UnitMyClass中看到的那样,没有对FormMain或FormEdit的引用
答案 6 :(得分:0)
FWIW,我在 CodeRage 9 视频中就这个主题做了一个完整的演示。可以在这里看到: