Как передать данные между формами в Delphi?

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

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

5
задан Kromster says support Monica 2 August 2014 в 17:38
поделиться

6 ответов

Я предлагаю отделить данные от 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;

Вы вызываете его, передаете GastedData, а затем вы показываете свою форму.

Затем, закрывая форму, вы выбираете обновление данных из элементов управления формы.

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. Таким образом вы отделили данные от графического интерфейса и можете легко подключить свою запись к нескольким различным формам.

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

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

9
ответ дан 18 December 2019 в 09:48
поделиться

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

3
ответ дан 18 December 2019 в 09:48
поделиться

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

implementation
{$R *.DFM}

Uses <Your Unit>;

end. 
1
ответ дан 18 December 2019 в 09:48
поделиться

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

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

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

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

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

0
ответ дан 18 December 2019 в 09:48
поделиться

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

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

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

2
ответ дан 18 December 2019 в 09:48
поделиться

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

Итак ... Форма заставки (основная форма):

. . .

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
ответ дан 18 December 2019 в 09:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: