[Решено] Проблема с динамическим созданием форм

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

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

[Решено] Проблема с динамическим созданием форм

Сообщение kotompazb » 31.10.2015 23:31:47

Здравствуйте.
В общем, попробую описать проблему, с которой столкнулся, как я предполагаю из-за своего непонимания, как действует механизм создания форм в принципе :(
Есть у меня проект, по сути это файловый менеджер, точнее менеджер содержимого очень специфичных архивов. И имеется в этом менеджере функция просмотра файла под курсором (похожая на Lister в TC). Ранее при вызове этой функции, я просто открывал нужную форму ShowModal. Естественно, основная форма приложения до закрытия формы становилась недоступна.
Сегодня я решил от этого избавиться, исключил форму из автосоздаваемых и стал создавать ее экземпляры так:
Код: Выделить всё
if FileInListSelected=true then begin
    fm := TFormTView.Create(Application);
    fm.Show;
end;

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

Не подскажите, как это побороть?
Или быть может просто где-то ошибка, тогда подскажите в какую сторону копать.
Очень уж не хочется откатываться к предыдущему варианту:(
Последний раз редактировалось kotompazb 05.11.2015 18:36:03, всего редактировалось 1 раз.
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Проблема с динамическим созданием форм

Сообщение Ism » 01.11.2015 02:46:54

Вы присваиваете указатель на новую форму одной и той же переменной fm, что чревато,
Создайте массив fm из указателей на создаваемые формы
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Проблема с динамическим созданием форм

Сообщение Снег Север » 01.11.2015 09:28:05

У нас в одном коммерческом проекте это было реализовано так - у форм был некоторый уникальный идентификатор-переменная. Указатели на форму запоминались в динамическом массиве. Когда надо было открыть форму, массив просматривался на предмет поиска по этому идентификатору. Если он присутствовал, открывалась уже созданная форма, нет - создавалась и запоминалась новая.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 3053
Зарегистрирован: 27.11.2007 16:14:47

Re: Проблема с динамическим созданием форм

Сообщение Vadim » 01.11.2015 11:47:37

Сделать список форм. Что-то типа:
Код: Выделить всё
TFormList = class(TList)
private
  function GetItem(Index: integer): TFormTView;
  function SetItem(Index: integer; const Value: TFormTView);
public
  property Items[Index: integer]" TFormTView read GetItem write SetItem; default;
end;

Теперь в списке можно сохранять вновь создаваемые формы и брать оттуда уже существующие, по индексу.
Код: Выделить всё
Var
  ListForm: TFormList;
Begin
  ...
  ListForm.Add(TFormTView.Create(Application));
  ...
  ListForm.Items[0].Метод_Вашей_Формы_Просмотра;
  ...

End;
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Проблема с динамическим созданием форм

Сообщение kotompazb » 01.11.2015 18:01:05

Ism писал(а):Вы присваиваете указатель на новую форму одной и той же переменной fm, что чревато,
Создайте массив fm из указателей на создаваемые формы

Пробовал и так:
Код: Выделить всё
var
    TView: array of TFormTView;

....

if FileInListSelected=true then begin
    SetLength(TView,Length(TView)+1);
    TView[High(TView)] := TFormTView.Create(Application);
    TView[High(TView)].Show;
end;

Результат тот же.

Снег Север писал(а):У нас в одном коммерческом проекте это было реализовано так - у форм был некоторый уникальный идентификатор-переменная. Указатели на форму запоминались в динамическом массиве. Когда надо было открыть форму, массив просматривался на предмет поиска по этому идентификатору. Если он присутствовал, открывалась уже созданная форма, нет - создавалась и запоминалась новая.


Vadim писал(а):Сделать список форм


В принципе, мне не надо помнить созданные формы - при открытии каждая из них получает кнопку на панели задач, и пока она не закрыта, этой кнопкой она и вызывается.
Суть проблемы в том, что на форме-листер имеется ряд кнопок - переключателей режима просмотра (текст, Hex, кодировки и т.д.), у них обработчики прописанные в модуле формы, которые обрабатывают динамический массив (с содержимым файла), объявленный в этом же модуле, заполняемый в обработчике onCreate. Открываем 2 файла на просмотр:
Код: Выделить всё
if FileInListSelected=true then begin
    SetLength(TView,Length(TView)+1);
    TView[High(TView)] := TFormTView.Create(Application);
    TView[High(TView)].Show;
end;

И вот, что получается:
Сразу после открытия:
Изображение
Видно, что содержимое файлов разное.
И при нажатии на любую из кнопок (одну и ту же на каждой форме естественно):
Изображение
Содержимое левой формы (открытой первой) стало таким же, как и содержимое последней открытой (справа).

Вот это хочется победить.

Добавлено спустя 2 часа 3 минуты 43 секунды:
Грешил еще на:
Код: Выделить всё
var
  FormTview: TFormTview;     

в модуле формы, закомментировал, не помогло:(
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Проблема с динамическим созданием форм

Сообщение WAYFARER » 01.11.2015 22:27:03

Добавьте свойство FileName для TFormTView и при создании экземпляра пишите в него путь к открываемому файлу. При переключении режима переоткрывайте файл беря его из FileName.
Аватара пользователя
WAYFARER
энтузиаст
 
Сообщения: 537
Зарегистрирован: 09.10.2009 00:00:04
Откуда: г. Курган

Re: Проблема с динамическим созданием форм

Сообщение kotompazb » 02.11.2015 02:06:43

WAYFARER писал(а):Добавьте свойство FileName для TFormTView и при создании экземпляра пишите в него путь к открываемому файлу. При переключении режима переоткрывайте файл беря его из FileName.

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

...короче, головой надо думать.
Перенес массивы и глобальные в public - все исправилось само собой, теперь осталось убедиться в том, что пытаясь найди ошибку, я не поломал чего...
Спасибо, всем за помощь.

Кстати, подскажите, как будет правильнее закрывать форму, ведь пользователь в процессе может открывать на просмотр множество файлов, и каждый раз будет создаваться новая форма...
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Проблема с динамическим созданием форм

Сообщение WAYFARER » 02.11.2015 02:24:15

kotompazb писал(а):Кстати, подскажите, как будет правильнее закрывать форму, ведь пользователь в процессе может открывать на просмотр множество файлов, и каждый раз будет создаваться новая форма...

в OnClose
Код: Выделить всё
CloseAction:=caFree; 
Аватара пользователя
WAYFARER
энтузиаст
 
Сообщения: 537
Зарегистрирован: 09.10.2009 00:00:04
Откуда: г. Курган

Re: Проблема с динамическим созданием форм

Сообщение kotompazb » 02.11.2015 03:02:36

WAYFARER писал(а):
kotompazb писал(а):Кстати, подскажите, как будет правильнее закрывать форму, ведь пользователь в процессе может открывать на просмотр множество файлов, и каждый раз будет создаваться новая форма...

в OnClose
Код: Выделить всё
CloseAction:=caFree; 

Спасибо.
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Проблема с динамическим созданием форм

Сообщение Vadim » 02.11.2015 10:11:00

kotompazb
А обработчик у Вас один и тот же для всех форм?
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Проблема с динамическим созданием форм

Сообщение kotompazb » 02.11.2015 10:37:52

Vadim писал(а):kotompazb
А обработчик у Вас один и тот же для всех форм?

Да. Один. Ожидать проблем?

Добавлено спустя 3 минуты 9 секунд:
Ну то есть один, для всех форм TFormTview.
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: Проблема с динамическим созданием форм

Сообщение Alex2013 » 05.11.2015 18:26:46

Может на мысли натолкнет моя тупейшая процедура "углубленного ShowMessage" ?
(Если честно не понял в чем проблема ... )
Код: Выделить всё
// Динамическая форма для вывода
// сообщений
Procedure WForm(M:String);
var
WF:TForm;
L:TLabel;
B:TButton;
SB:TScrollBox;
p,PS:Tpanel;
begin
WF:=TForm.create(nil);
  ps:=Tpanel.Create(wf);
  PS.Align:=alClient;
Sb:= TScrollBox.create(ps);
//Sb.Width:=548;

sb.VertScrollBar.Visible:=true;
sb.AutoScroll:=true;
SB.Height:=250;
sb.Align:=alClient;;

wf.Top:=50;
wf.left:=25;
Wf.Width:=550;
Wf.Height:=250;

  p:=Tpanel.Create(wf);
  P. Height:=55;
  p.Align:=alBottom;

  B:=TButton.Create(p);
  B.Caption:='Ok';

  b.Left:=20;
  b.Top:=5;
  b.ModalResult:=1;

L:=TLabel.Create(Sb);
l.Align:=alTop;
l.Top:=20;
l.Left:=20;
l.Font.Height:=14;
l.Caption:=m;

wf.InsertControl(p);
p.InsertControl(B);

wf.InsertControl(ps);
Ps.InsertControl(Sb);
sb.InsertControl(l);
wf.ShowModal;
wf.Free;
end;                                 

Если дело в обработчике то в нем нужно определять откуда идет запрос

Код: Выделить всё
// Обработчик клавишь для главной формы

Const
      //CC:TControl=nil;
      CI:Longint=1;
      MinI:Longint=1;
Var
  SCI,SMinI:Longint;

procedure TWQ_MForm.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);

begin

   If TForm(Sender).ControlCount>0 then
   begin
    Case key of
       vk_Up    :If Ci >MinI then begin
                      TPanel(TForm(Sender).Controls[ci]).Color:=ColorBatton;
                      //$F0FFFF;
                      Dec(CI,1);
                      TPanel(TForm(Sender).Controls[ci]).Color:=ColorABatton
                     // $FFFF;
       end;
       vk_Down  : if CI < TForm(Sender).ControlCount-(1+MinI) then begin
                      TPanel(TForm(Sender).Controls[ci]).Color:=ColorBatton;
                      //$F0FFFF;
                      Inc(CI,1);
                      TPanel(TForm(Sender).Controls[ci]).Color:=ColorABatton;
                      //$FFFF;
      end;
     vk_Return:begin Button1Click(TForm(Sender).Controls[ci]); end;
     end;
    end;
    //TWQ_MForm.Controls[];
end;

Обрати внимание на эту сточку
vk_Return:begin Button1Click(TForm(Sender).Controls[ci]); end;
А в Button1Click делаешь на пример как-то так
S:=TButton(Sender).Hint;
Case s of
...
Последний раз редактировалось Alex2013 05.11.2015 18:50:39, всего редактировалось 1 раз.
Alex2013
долгожитель
 
Сообщения: 3145
Зарегистрирован: 03.04.2013 11:59:44

Re: Проблема с динамическим созданием форм

Сообщение kotompazb » 05.11.2015 18:35:25

Alex2013 писал(а):Если честно не понял в чем проблема ...

Да все уж решил. Спасибо.
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: [Решено] Проблема с динамическим созданием форм

Сообщение Alex2013 » 05.11.2015 18:51:35

Ну может еще кому-то пригодится ...
Alex2013
долгожитель
 
Сообщения: 3145
Зарегистрирован: 03.04.2013 11:59:44


Вернуться в Lazarus

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

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

Рейтинг@Mail.ru