2010-06-02 4 views
4

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

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

+0

могли бы вы рассказать немного о ваших формах. Я не уверен, что я вполне понимаю, какие формы у вас есть, и кто их инициировал, и кто должен создавать объект, и передать его кому. – Ivan

+0

Вся программа такова: заставка запускает форму (form1) для получения данных от пользователя. и когда пользователь нажимает OK на form1, ему необходимо отправить полученные данные другому классу (менеджеру), чтобы создать объект с этими данными и использовать его. Оба всплеска и form1 должны быть закрыты, и после отправки я их больше не нуждаюсь. – Mahm00d

ответ

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; 

Вы называете его, пройти GatheredData, а затем вы показываете свою форму.

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

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

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

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

+0

Большое вам спасибо за подробный и отличный ответ. Возможно, я задал вопрос неправильно или не дал хороших подробностей. У меня есть развязанный код (мой класс менеджера находится в другом блоке) и не имеет ничего общего с формой. Проблема в том, что даже если я использую запись для хранения, как передать ее менеджеру? Он находится в классе формы, и форма не имеет доступа к классу менеджера (я предпочитаю, чтобы он этого не делал!). Итак, как вы его проходите? Я хочу, чтобы менеджер имел доступ к различным формам, а не к визе. – Mahm00d

+0

Может быть, я что-то не понимаю. У вас должно быть по крайней мере три единицы. 1 - который содержит только определение данных, 2 - единица, в которой содержится ваш класс Manager, который принимает данные в качестве параметра и 3 - форму, которая принимает данные в качестве параметра. Что именно делает ваш менеджер? – Wodzu

+0

Это точно так. У меня также есть основная форма, отличная от той, которая получает данные. Если вы знаете шаблоны OOD, мой менеджер является режиссером для пользовательского интерфейса, который управляет данными между формами и вносит изменения. Не важно, что именно делает менеджер. Я задаю свой вопрос по-другому: Есть ли способ передать данные экземпляру класса без прямого доступа к нему (без использования «use ...» в интерфейсе)? – Mahm00d

1

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

implementation 
{$R *.DFM} 

Uses <Your Unit>; 

end. 
+0

Я знаю этот метод, но я с нетерпением жду других возможностей. Спасибо в любом случае. – Mahm00d

3

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

2

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

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

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

+0

+1 для вашего хорошего решения. Кажется, что легко настроить и хорошо заменить большие и труднодоступные базы данных. Это действительно хороший способ отделить дату от других компонентов. Спасибо. – Mahm00d

+0

@Fiom - Приятно слышать. Чтобы быть ясным, использование самого Datamodule не имеет никакого отношения к тому, как хранятся ваши данные. Ваш datamodule может включать компоненты, которые обращаются к данным в базе данных, datastructures с компонентами формы, такими как TStringList или datastructures, которые полностью созданы в коде. Независимо от того, что вы делаете, рекомендуется размещать общие данные в datamodule и использовать модуль datamodule всеми формами, которым необходим доступ к данным. –

0

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

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

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

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

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

2

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

Итак ... Всплеск форма (Main форма):

. . .

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. 

DataForm является:

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; 

Вам нужно будет заполнить в остальной части блока кода и бесплатно некоторые вещи, но по существу это:

Start Program (Создает Всплеск)

Всплеск Создает менеджер называет его, чтобы получить данные из DataForm затем скрывает себя

менеджер

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

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

Там нет другого пути, чтобы закрыть его в настоящее время, кроме как через диспетчер задач!)

Tim

Смежные вопросы