Это может казаться маленьким новичком, но у меня действительно есть проблема с ним. У меня есть форма (не основная) для получения многих различных данных от пользователя, и я хочу передать его классу менеджера для создания объекта с ними. Проблема состоит в том, что у меня не может быть этого класса для использования другой единицы (получение кругового использования), и также это не имеет доступа к экземпляру класса менеджера (который находится в основной форме).
Так, что я сделаю? Я уже рассмотрел использование общедоступной переменной, но у меня есть плохое чувство об этом (относительно шаблонов OOD).
Я предлагаю отделить данные от 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. Таким образом вы отделили данные от графического интерфейса и можете легко подключить свою запись к нескольким различным формам.
Просто не забудьте объявить свой тип записи во внешнем модуле и использовать этот модуль в своем модуле менеджера и сформировать модуль.
Надеюсь, это немного поможет.
«Класс менеджера» не должен входить ни в одну из форм, а в отдельный. Отделив код графического интерфейса от бизнес-логики, вы избежите подобных проблем.
Чтобы решить ошибку циркулярного обращения, вы используете этот блок в разделе реализации.
implementation
{$R *.DFM}
Uses <Your Unit>;
end.
Имея эти 3 единицы: FormMain FormEdit UnitMyClass
Вы создаете свой объект в FormMain и передаете его в FormEdit с помощью такой функции, как:
class function FormEdit.EditMyObject(AObject: TMyClass): boolean;
эта функция покажет модальную форму. Форма внесет изменения в объект и, наконец, вернет True, если пользователь нажал OK.
Как видите, в UnitMyClass нет ссылки на FormMain или FormEdit
[Edit: изначально я поместил этот ответ в комментарий, но решил переместить его в полный ответ. TDatamodules слишком важны и слишком распространены в Delphi, чтобы не акцентировать на них внимание, и они предоставляют встроенные простые в использовании средства отделения графического интерфейса от логики и данных.]
Другие люди дали хорошие комментарии по поводу отделения графического интерфейса от логики и данных. данные. Удивительно, но я не думаю, что кто-то упомянул, что в Delphi TDatamodules являются одним из основных средств для этого. Вы помещаете свои данные и логику в Datamodule, а затем обе формы "используете" Datamodule для получения доступа к его данным и методам. Вот краткое введение: http://delphi.about.com/od/database/l/aa101601a.htm
Обе ваши формы (и другие формы) могут получать доступ к наборам данных или другим данным / структурам данных, которые расположены на / в модуле Datamodule. Там должен быть легко найти образец проекта, иллюстрирующий настройку, поскольку это (или, по крайней мере, был) стандартный способ создания приложений Delphi.
Если я правильно понимаю ваш вопрос, вы хотите, чтобы менеджер управлял формами (а не формами для доступа к менеджеру). Верно? Вы не можете закрыть основную форму, как если бы вы закрывали приложение, но вы МОЖЕТЕ скрыть ее. (если вы не создаете консольное приложение). Но это создает небольшую приятную проблему :)
Итак ... Форма заставки (основная форма):
. . .
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 Создает диспетчер, вызывает его для получения данных из формы данных, затем скрывает себя
вызывает диспетчер для управления данными
, когда диспетчер завершает работу, он затем закрывается.
Сейчас нет другого способа выключить его, кроме как через диспетчер задач!)
Тим