[Решено] ОбработкаПодбора() в лазарусе

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

[Решено] ОбработкаПодбора() в лазарусе

Сообщение yeger » 08.09.2011 13:21:00

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

В 1С есть процедура ОбработкаПодбора(<Элемент>,<КонтФормы>) (Обработка подбора значения при нажатия кнопки Выбрать в Форме Подбора значения). И все в общем то очевидно.

Есть ли что-то подобное в Lazaruse? Если нет, как это сделать?
Последний раз редактировалось yeger 15.11.2011 11:56:09, всего редактировалось 1 раз.
Аватара пользователя
yeger
новенький
 
Сообщения: 49
Зарегистрирован: 17.03.2011 12:26:34

Re: ОбработкаПодбора() в лазарусе

Сообщение dunin » 08.09.2011 13:46:33

Если дочернюю форму все равно прибивать, то почему ей не красиво быть модальной?
Аватара пользователя
dunin
энтузиаст
 
Сообщения: 634
Зарегистрирован: 02.05.2007 13:18:11
Откуда: Тољя††и

Re: ОбработкаПодбора() в лазарусе

Сообщение Padre_Mortius » 08.09.2011 13:48:06

Обработать событие OnClose в дочерней форме и передать нужные параметры главной форме
Padre_Mortius
энтузиаст
 
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Re: ОбработкаПодбора() в лазарусе

Сообщение dunin » 08.09.2011 13:52:15

Код: Выделить всё
procedure DochernayaForma.BtnZabratClick(Sender: tobject);
begin
  ... // что-то делаем
  GlavnayaForma.ZabratRezultat; // вызываем процедуру описанную в модуле главной формы
  DochernayaForma.Close; // закрываем дочернюю
end;

или как-то так или я вопроса не понял...
Аватара пользователя
dunin
энтузиаст
 
Сообщения: 634
Зарегистрирован: 02.05.2007 13:18:11
Откуда: Тољя††и

Re: ОбработкаПодбора() в лазарусе

Сообщение yeger » 08.09.2011 15:07:30

Код: Выделить всё
procedure DochernayaForma.BtnZabratClick(Sender: tobject);
begin
  ... // что-то делаем
  GlavnayaForma.ZabratRezultat; // вызываем процедуру описанную в модуле главной формы
  DochernayaForma.Close; // закрываем дочернюю
end;

Вопрос понят правильно. А как дочерняя узнает что у главной есть метод "ZabratRezultat"? откуда вообще взялась переменная GlavnayaForma?
Если объявить модуль главной в дочерней будет "круговая" ссылка, что противоречит логике самого языка.

Думал о пользовательском событии (Отправлять родителю событие формы) но в описаниях и мнениях запутался...

"почему ей не красиво быть модальной" - потому что блокирует предыдущие окна. Открыл документ, в нем справочник, в нем подбор справочника и т.д. и все это модально....
Аватара пользователя
yeger
новенький
 
Сообщения: 49
Зарегистрирован: 17.03.2011 12:26:34

Re: ОбработкаПодбора() в лазарусе

Сообщение alexs » 08.09.2011 18:34:39

yeger писал(а):А как дочерняя узнает что у главной есть метод "ZabratRezultat"? откуда вообще взялась переменная GlavnayaForma?

Объяви у дочерней в приватной секции переменную типа "Главная Форма"
При создании дочерней прописывай туда ссылку на главную форму
Вот и все всё будут знать.
yeger писал(а):Если объявить модуль главной в дочерней будет "круговая" ссылка, что противоречит логике самого языка.

Противоречие возникает если ты объявляешь обоих подключение модулей в соответсующих секция интерфейса.
Но никто не мешает тебе объявить модуль дочерней формы в разделе реализации (implementation)
И всё будет работать правильно.
Ну а насчёт события когда надо передавать - ттебе уже указали - OnClose у дочерней формы.

Внимание!
В приведённом методе кроется одна засада - что будет, если закроют главную форму раньше, чем закроют дочернюю?
Решается просто:
- можно всем формам посылать уведомление через событие с кодом события "Закрытие моей любимой главной формы" и указыват экземпляр этйо формы.
- можно в главной форме сразу объявить коллекцию указателей на её дочернии формы (тут надо будет не забыть убирать дочернюю из коллекции при закрытии дочерней)

Можно ещё чего придуматью.
Также вопрос - что ты будешь делать с дочерними - если закрыли главную?

Все прелисти многодокументного неблокирующего интерфейса для программера. Но с другой стороны, обычно такая метода более удобная для пользователя.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: ОбработкаПодбора() в лазарусе

Сообщение yeger » 08.09.2011 23:27:48

Вопрос ведь не звучал "когда", а "как".
Не красивое решение же. Придется добавлять каждый из возможных родителей в implementation.
Есть мысль: сделать свой компонент, назовем "TFormWithEventSelect", и использовать его как родителя всех прикладных форм.
Для "TFormWithEventSelect" определить событие, назовем "OnSelectInChild", для которого в свою очередь передавать, положим имя подчиненной формы.

Такой вариант реализуем средствами lazarus?
Если да, прошу поделиться ссылками на справку по теме или примером.
Аватара пользователя
yeger
новенький
 
Сообщения: 49
Зарегистрирован: 17.03.2011 12:26:34

Re: ОбработкаПодбора() в лазарусе

Сообщение kipar » 09.09.2011 00:13:27

Есть мысль: сделать свой компонент, назовем "TFormWithEventSelect", и использовать его как родителя всех прикладных форм.

Можно и не делать компонент, а просто Файл\Создать\Унаследованный элемент.
kipar
новенький
 
Сообщения: 78
Зарегистрирован: 04.03.2010 12:15:54

Re: ОбработкаПодбора() в лазарусе

Сообщение alexs » 09.09.2011 00:14:23

yeger писал(а):Придется добавлять каждый из возможных родителей в implementation.

Коков был вопрос - таков и ответ.
Я привёл только 2 способа решения. Можно ещё напридумывать кучу.
yeger писал(а):сделать свой компонент, назовем "TFormWithEventSelect", и использовать его как родителя всех прикладных форм

Визуальное наследвание.
Можно использоват интерфейсы.

Добавлено спустя 5 минут 24 секунды:
kipar писал(а):Можно и не делать компонент, а просто Файл\Создать\Унаследованный элемент.

Вместе ответили :-)
yeger
Ещё раз повторюсь - всё зависит от вашей проблемы. Мы тут предлагаем общие пути решения. только специфика вашей задачи определит тот путь (может единственный, может несколько альтернатив), который необходимо использовать.

P.S.
Я в своих проектах для многодокументального интерфейса использую в основном 2-й метод из своего 1-го ответа. Там именно основной список документов и из него создание/открытие существующего документа. После изменения/закрытия документа основной список пересчитывается по необходимости. Хотя в некоторых местах используются и 1-й пример, и события-сообщения, и интерфейсы...
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: ОбработкаПодбора() в лазарусе

Сообщение yeger » 15.11.2011 11:47:08

Не прошло и пол года, как ответ был найден. Основная проблема для аналога "ОбработкаПодбора()" это тот факт, что дочернее окно "ничего не знает" о главном.
Не буду "растекаться мыслею", а перейду к сути:
- в главной форме определяем в "published" секции процедуру обработки подбора. Пусть так:
Код: Выделить всё
  TFrmRefCur = class(TForm)
    procedure OpenChild(Sender: TObject);// <- Вызов подчиненной формы
  private
    { private declarations }
  public
    { public declarations }
  published
    { much public declarations }
    procedure ItWasMade(ByForm:TForm); // <- А вот и обработка подбора
  end;

Вызов подчиненной формы оригинальностью не отличается
Код: Выделить всё
procedure TFrmRefCur.OpenChild(Sender: TObject);
var
  FCurrecy: TFrmEditRefCur;//класс наследник TForm описан в другом модуле указанном в uses
begin
  FCurrecy:=TFrmEditRefCur.Create(Self);
  FCurrecy.Show;
end;

Пусть эта процедура пока вернет нам лишь имя класса её вызвавшего:
Код: Выделить всё
procedure TFrmRefCur.ItWasMade(ByForm:TForm);
begin
  ShowMessage(ByForm.Name);
end;

В модуле подчиненной формы объявляем тип реализующий процедуру главной формы (т.к. подчиненная не знает о функциях главной) и собственно подчиненную форму:
Код: Выделить всё
type
  TExecute = procedure(Who:TForm) of object; //<- тип реализующий процедуру главной формы
  { TFrmEditRefCur }
  TFrmEditRefCur = class(TForm)
    BtnOk: TBitBtn;
    procedure BtnOkClick(Sender: TObject);//<- дескать выбираем что-то
  private
    { private declarations }
  public
    { public declarations }
    procedure MakeIt (Who:TForm);//<- вот тут передадим в обработку подбора
  end;

И, собственно реализуем вызов процедуры главной формы:
Код: Выделить всё
procedure TFrmEditRefCur.MakeIt (Who:TForm);
var
   Routine: TMethod;
   Execute: TExecute;
begin
   Routine.Data := Pointer(Who.Owner);
   // Returns the address of a published method.
   Routine.Code := Who.Owner.MethodAddress(Utf8ToAnsi('ItWasMade'));
   if Routine.Code <> nil then
   begin
      Execute := TExecute(Routine);
      Execute(Who);
   end;
end;

procedure TFrmEditRefCur.BtnOkClick(Sender: TObject);
begin
  Close;
  MakeIt(Self);
end;

"Прибивание" подчиненных окон хорошо описал alexs выше.
Еще пример вызова метода по наименованию тут: http://www.kansoftware.ru/?tid=468
Аватара пользователя
yeger
новенький
 
Сообщения: 49
Зарегистрирован: 17.03.2011 12:26:34


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 14

Рейтинг@Mail.ru