如何在Delphi中的表单之间传递数据?

时间:2010-06-02 08:48:17

标签: delphi forms

这可能看起来有点新手,但我确实遇到了问题。我有一个表单(不是主要表单)从用户那里获取许多不同的数据,我想将它传递给一个管理器类来创建一个带有这些的对象。问题是我不能让这个类使用其他单元(获得循环使用),并且它也无法访问经理类实例(主要形式)。

那么,我该怎么办?我已经考虑过使用公共变量,但我对此感觉不好(关于OOD模式)。

7 个答案:

答案 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 视频中就这个主题做了一个完整的演示。可以在这里看到:

https://youtu.be/qqKx8fQTTfI