Как передавать данные между формами в Delphi? - PullRequest
5 голосов
/ 02 июня 2010

Может показаться немного новичком, но у меня действительно есть проблемы с этим.У меня есть форма (не основная) для получения множества различных данных от пользователя, и я хочу передать ее классу менеджера для создания объекта с этими данными.Проблема в том, что у меня не может быть этого класса для использования другого модуля (используется круг), а также у него нет доступа к экземпляру класса менеджера (который находится в основной форме).

Итак,что мне делать?Я уже рассмотрел использование публичных переменных, но у меня плохое предчувствие (относительно шаблонов OOD).

Ответы [ 6 ]

8 голосов
/ 02 июня 2010

Я предлагаю отделить данные от GUI , потому что это вызывает вашу проблему. Если у вас есть форма, которая собирает данные от пользователя, вы должны отличать данные от формы (TForm).

Например, давайте предположим, что у вас есть некоторый экземпляр TForm и форма, которая построена из трех полей: имя пользователя, возраст и местоположение. Вы хотите, чтобы пользователь ввел эти три вещи, но когда пользователь закрывает форму, вы должны передать эти вставленные данные в некоторый объект. Форма закрывается, она освобождается, но объект сохраняется. Затем вы передаете этот объект вашему менеджеру.

Простой пример:

Это ваша запись, которая будет хранить данные

type
  TGatheredData = record
    Name: String[40];
    Age: Byte;
    Location: String[40];
end;

Ваш TForm1 может иметь дополнительный конструктор:

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;

Вы называете это, передаете GotedData, а затем вы показываете свою форму.

Далее при закрытии формы вы выбираете 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;

Имея эту запись данных, вы теперь можете таким же образом передать ее своему менеджеру. Таким образом вы развязали данные от GUI и можете легко подключать свои записи к различным формам.

Просто не забудьте объявить свой тип записи во внешнем модуле и использовать этот модуль в своем модуле менеджера и модуле.

Надеюсь, это немного поможет.

3 голосов
/ 02 июня 2010

«Класс менеджера» должен быть не в какой-либо форме, а в отдельном. Отделяя код GUI от логики бизнеса, вы избегаете таких проблем, как эта.

2 голосов
/ 04 июня 2010

Если я правильно понимаю ваш вопрос, то вы хотите, чтобы менеджер управлял формами (а не формами для доступа к менеджеру). Правильно? Вы не можете закрыть основную форму, как если бы вы закрывали приложение, но вы МОЖЕТЕ скрыть ее. (если вы не создадите консольное приложение). Но это создает небольшую проблему:)

Итак ... Форма всплеска (Основная форма):

. , .

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 Создает диспетчер, вызывает его, чтобы получить данные из формы данных, а затем скрывается

звонит менеджеру для управления данными

когда менеджер готов, он закрывается.

Нет другого способа выключить его сейчас, кроме как через диспетчер задач!)

Тим

2 голосов
/ 02 июня 2010

[Edit: я первоначально поместил этот ответ в комментарии, но решил переместить его в полный ответ.TDatamodules слишком важны и слишком распространены в Delphi, чтобы не подчеркивать их, и они предоставляют встроенные простые в использовании средства отделения графического интерфейса от логики и данных.]

Другие люди дали хорошие комментарии по поводу отделения графического интерфейса отлогика и данные.Удивительно, но я не думаю, что кто-то упомянул, что в Delphi TDatamodules являются одним из основных способов сделать это.Вы помещаете свои данные и логику в модуль данных, а затем обе формы «используют» модуль данных, чтобы получить доступ к его данным и методам.Вот краткое введение: http://delphi.about.com/od/database/l/aa101601a.htm

Обе ваши формы (и другие формы) могут получить доступ к наборам данных или другим данным / структурам данных, которые находятся в / в модуле данных.Там должно быть легко найти пример проекта, иллюстрирующего настройку, так как это (или, по крайней мере, был) стандартный способ создания приложений Delphi.

1 голос
/ 02 июня 2010

Чтобы устранить ошибку циклического референса, используйте эту единицу в разделе реализации.

implementation
{$R *.DFM}

Uses <Your Unit>;

end. 
0 голосов
/ 02 июня 2010

Имея это 3 единицы: FormMain FormEdit UnitMyClass

Вы создаете свой объект в FormMain и передаете его в FormEdit в функции, подобной:

class function FormEdit.EditMyObject(AObject: TMyClass): boolean;

эта функция покажет модальную форму. Форма внесет изменения в объект и, наконец, вернет True, если пользователь нажал OK.

Как вы можете видеть в UnitMyClass, нет ссылки на FormMain или FormEdit

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...