Модераторы: Snowy, MetalFan, bems, Poseidon

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как правильно реализовать окно "Ждите.. (Гот.X%)" 
:(
    Опции темы
gesper
Дата 18.5.2012, 02:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


"Shарфик"
*


Профиль
Группа: Участник
Сообщений: 183
Регистрация: 23.2.2005

Репутация: 1
Всего: 2



Вопрос в следующем, есть программа функции которой выполняют разнообразную деятельность причем порой очень долго.
Я сделал окошко, которое создается при начале работы таких "долгих" функций и уничтожается по их окончанию.
Работа с ним ведется вот в таком варианте:

Код

procedure TF.....ImportDataFromFile(FileName:String);
var
  ...
  ProgressForm:TFProgressForm;
begin
if fileexists(FileName)then
begin
   ...
   try
      ProgressForm:=TFProgressForm.Create(Self);
      ProgressForm.ShowProgressWindow(False,'Подготовка...',0);
      ...

      ProgressForm.SetNewStatus('Загрузка данных, ждите...',0);
      ...

      ProgressForm.SetNewStatus('Обновление списков...',0);
      ...

   finally
        ProgressForm.HideProgressWindow('Готово',0);
        ProgressForm.Free;
   end;
end;
end;



Это все чудесно работает, но хочется понять как сделать чтобы не привязывая функции загрузки данных имеющиеся к элементам форм изменять значения о ходе процесса загрузки.
Т.е. есть функции которые типовые и вызываются в разных формах для загрузки, к примеру XML в TreeView. Такая функция долго обрабатывает файл, там много позиций, она их фильтрует и грузит. Все это время весит окошко "Ждите... ваша очередь скоро наступит". Вот как сделать, чтобы функция меняла какое то integer значение и тем самым показывала сколько она прошла уже.
Я где то видел, как в функцию передавали Pointer на переменную которая отображала ход прогресса, но не помню где.
--------------------
...И приколется обломившийся и oбломится приколовшийся...
PM MAIL   Вверх
Akella
Дата 19.5.2012, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Творец
****


Профиль
Группа: Модератор
Сообщений: 18485
Регистрация: 14.5.2003
Где: Корусант

Репутация: 8
Всего: 329



такие вопросы в раздел для Новичков

Добавлено @ 13:39
в чем сложно в длинном цикле добавить 2 строки

Код


создаем и показываем форму с процессбаром
но не в коем случае в модальном режиме ибо все управление перейдет сразу модульному окну

for i:=0 to count-1 do 
begin

что-то делаем

показываем процесс
form_process.progressbar1.position := i
application.processmessages;


end;

уничтожаем форму спроцессбаром

не забываем про try execpt\finally
PM MAIL   Вверх
Alexeyt
Дата 24.5.2012, 18:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 332
Регистрация: 15.9.2006
Где: около Москвы

Репутация: нет
Всего: 2



Поместить на форму TProgressBar/ TGauge. + ответ выше
PM WWW   Вверх
gesper
Дата 25.5.2012, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


"Shарфик"
*


Профиль
Группа: Участник
Сообщений: 183
Регистрация: 23.2.2005

Репутация: 1
Всего: 2



Ребят, а может внимательно читать будете?

Цитата

 как сделать чтобы не привязывая функции загрузки данных имеющиеся к элементам форм изменять значения о ходе процесса загрузки.


Понятно, что на форму надо кинуть TProgressBar, но некакого упоминания о нем в цикле функции быть не должно!
Я от вас хочу, как сделать связь между progressbar1.position и какой то переменной передаваемой в цикл. Точнее адрес наверно переменной.
--------------------
...И приколется обломившийся и oбломится приколовшийся...
PM MAIL   Вверх
northener
Дата 26.5.2012, 00:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(gesper @  25.5.2012,  19:56 Найти цитируемый пост)
Ребят, а может внимательно читать будете?

Цитата

 "как сделать чтобы не привязывая функции загрузки данных имеющиеся к элементам форм изменять значения о ходе процесса загрузки."

Да просто никто (и я в том числе) не понял вот этого вопроса.

Тем более смущает высказывание 
Цитата(gesper @  18.5.2012,  02:47 Найти цитируемый пост)
Я где то видел, как в функцию передавали Pointer на переменную которая отображала ход прогресса, но не помню где. 

Похоже вы ищеете "то, не знаю что".  Но и мы тоже не знаем. (((
Лучше объясните задачу. Зачем нужно, 
Цитата(gesper @  25.5.2012,  19:56 Найти цитируемый пост)
но некакого упоминания о нем в цикле функции быть не должно!




--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
gesper
Дата 27.5.2012, 16:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


"Shарфик"
*


Профиль
Группа: Участник
Сообщений: 183
Регистрация: 23.2.2005

Репутация: 1
Всего: 2



Цитата(northener @ 26.5.2012,  00:51)
Цитата(gesper @  25.5.2012,  19:56 Найти цитируемый пост)
Ребят, а может внимательно читать будете?

Цитата

 "как сделать чтобы не привязывая функции загрузки данных имеющиеся к элементам форм изменять значения о ходе процесса загрузки."

Да просто никто (и я в том числе) не понял вот этого вопроса.

Тем более смущает высказывание 
Цитата(gesper @  18.5.2012,  02:47 Найти цитируемый пост)
Я где то видел, как в функцию передавали Pointer на переменную которая отображала ход прогресса, но не помню где. 

Похоже вы ищеете "то, не знаю что".  Но и мы тоже не знаем. (((
Лучше объясните задачу. Зачем нужно, 
Цитата(gesper @  25.5.2012,  19:56 Найти цитируемый пост)
но некакого упоминания о нем в цикле функции быть не должно!

Зачем нужно написал в самом начале. Показывать, что программа не зависла и сколько она выполнила уже.

Фунция обработки данных работает с классами и данными в них и только, некаких строчек о работе с компонентами формы в ней не должно быть, изменять значение прогресса она должна через переменную с адресом. Проблема в том, что нельзя взять указатель на "ProgressBar1.Position" и передать его в функцию.
--------------------
...И приколется обломившийся и oбломится приколовшийся...
PM MAIL   Вверх
Alexeyt
Дата 27.5.2012, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 332
Регистрация: 15.9.2006
Где: около Москвы

Репутация: нет
Всего: 2



Сделать callback. заведи ф-цию типа

type TFun=procedure (N: integer) of object;

и передавай ее адрес в расчет. 
procedure Расчет(....; f: TFun; ...)
В расчете делай

if f<>nil then
  f(N_процент);




Это сообщение отредактировал(а) Alexeyt - 27.5.2012, 16:21
PM WWW   Вверх
gesper
Дата 27.5.2012, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


"Shарфик"
*


Профиль
Группа: Участник
Сообщений: 183
Регистрация: 23.2.2005

Репутация: 1
Всего: 2



Цитата(Alexeyt @ 27.5.2012,  16:19)
Сделать callback. заведи ф-цию типа

type TFun=procedure (N: integer) of object;

и передавай ее адрес в расчет. 
procedure Расчет(....; f: TFun; ...)
В расчете делай

if f<>nil then
  f(N_процент);

Сделал сейчас через "третью ногу". Создал переменную в форме, где прогресс бар лежит, и ее адрес передаю, а обновление прогресса таймером выполняю. Но мне такой цирк не подуше, твой вариант больше нравится. Спасибо.
--------------------
...И приколется обломившийся и oбломится приколовшийся...
PM MAIL   Вверх
Dapo
Дата 27.5.2012, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 417
Регистрация: 18.4.2002

Репутация: нет
Всего: 1



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

Это сообщение отредактировал(а) Dapo - 27.5.2012, 20:01
PM MAIL   Вверх
gesper
Дата 27.5.2012, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


"Shарфик"
*


Профиль
Группа: Участник
Сообщений: 183
Регистрация: 23.2.2005

Репутация: 1
Всего: 2



Цитата(Dapo @ 27.5.2012,  19:55)
gesper, дружище! Если я правильно понял - то с примером предложенным тебе ты также точно попадаешь на ав в случае отсутствия функции (т.е. приявзка таки есть никуда ты от нее не денешься), либо тебе надо будет ставить заглушку в виде пустышки этой самой функции. Предположу, что то, что ты хочешь сделать должно лежать где-то в библиотеке, а юзать библиотеку может совсем другой твой апп? Возможно тебе поможет (но тоже нестопроцентов) регистрация собственного сообщения? в библиотеке ты можешь юзать свою функцию как хочешь, а главное окно аппа будет отрабатывать так как тебе захочется  (и если захочется),  возможность отследить ход процесса - фича твоей библиотеки.

Я в потоке твоих мыслей запутался, если чесно. smile

В предложеном варианте нет проблем, вот как это вглядит:

Код


uses ..., u_progressreportform_form;

function LoadCableDataToTreeNode(Tree:TTreeView;MainNode:TTreeNode;CableList:TList;AProgress:TProgressChange):boolean;
var
...
begin
...
  Result:=False;
  try
      Tree.Items.BeginUpdate;

          For i:=0 to CableList.Count-1 do
          begin
              if assigned(AProgress) then
                AProgress(0,CableList.Count-1,i,1,2);
              ....
          end;

      Tree.Items.EndUpdate;
      Result:=True;
  finally
    ...
  end;

end;

procedure TFEditor.LoadDataToList; // Пользователь запускает работу этой функцией
var
  CableLabel:string;
  i:integer;
  ProgressForm:TFProgressForm;
begin
  ProgressForm:=TFProgressForm.Create(Self);
  ProgressForm.ShowProgressWindow(False,'Подготовка...',0);
  try

      ProgressForm.SetNewStatus('Загрузка данных, ждите...',0);

      LoadCableDataToTreeNode(tvInDBCables,nil,CableList,ProgressForm.ProgressChange); // см. выше функцию

      ProgressForm.SetNewStatus('Создаются списки фильтров, ждите...',0);
      ...

  finally
    ProgressForm.HideProgressWindow('Готово',0);
    ProgressForm.Free;
  end;
end;


Задача чтобы можно было использовать LoadCableDataToTreeNode везде где понадобится дерево с записями БД, и не переделывать его под конкретный диалог, окно и т.п.
Но оно может долго очень грузится, вот и нужен прогресбар.
Итог:
procedure TFEditor.LoadDataToList; и function LoadCableDataToTreeNode внутри одного модуля, вторую можно использовать и вызывать из других форм, что я и делаю.
А TFProgressForm он общий и в нем просто есть нужна процедура для обновления прогресс бара, вот она:

Код

unit u_progressreportform_form;

type
  TProgressChange=procedure(Min,Max,Progress,Step,Steps:integer) of object;

// В параметрах предаются границы в которых идет прогресс выполнения и какой 
// из шагов по счету меняется, это на случай нескольких циклов в программе.
procedure TFProgressForm.ProgressChange(Min, Max, Progress, Step, Steps: integer);
var
  AStep,P1,P2:Integer;
begin
  AStep:=Round(100/steps);
  P1:=AStep*(Step-1);
  Max:=Max-Min;
  Progress:=Progress-Min;
  P2:=Round(Progress/(Max/AStep));
  ProgressBar1.Position:=P1+P2;
  ProgressBar1.Visible:=True;
  application.ProcessMessages;
end;


Это сообщение отредактировал(а) gesper - 27.5.2012, 22:06
--------------------
...И приколется обломившийся и oбломится приколовшийся...
PM MAIL   Вверх
Чучмек
Дата 28.5.2012, 00:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: 7
Всего: 41



Передавай  в свою "длгую" функцию  адрес переменной из TFProgressForm (var,const,@/pointer)
а в TFProgressForm, по таймеру, обновляй состояние ProgressBar в соответствии с этой переменной.
Только  если TFProgressForm и долгая функция в разных потоках,а так и должно быть, - не забывай про синхронизацию  InterlockedIncrement 


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
northener
Дата 28.5.2012, 00:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(Чучмек @  28.5.2012,  00:33 Найти цитируемый пост)
Только  если TFProgressForm и долгая функция в разных потоках,а так и должно быть

Вот тут поспорю со столь декларативным утверждением должно быть.  Почему именно должно? Если нормальное продолжение работы программы возможно только после выполнения той самой длительной функции, то зачем использовать другой поток? 


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
Чучмек
Дата 28.5.2012, 01:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: 7
Всего: 41



Ну если функция ничего не должна знать о TFProgressForm  - идем дальше - она не обязана знать об application


--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
northener
Дата 28.5.2012, 01:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(Чучмек @  28.5.2012,  01:02 Найти цитируемый пост)
Ну если функция ничего не должна знать о TFProgressForm  - идем дальше - она не обязана знать об application

Это уже перебор! Имхо.
Автор просто запутался в трёх соснах пока искал "волшебную палочку".


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
gesper
Дата 28.5.2012, 01:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


"Shарфик"
*


Профиль
Группа: Участник
Сообщений: 183
Регистрация: 23.2.2005

Репутация: 1
Всего: 2



Цитата(Чучмек @ 28.5.2012,  00:33)
Передавай  в свою "длгую" функцию  адрес переменной из TFProgressForm (var,const,@/pointer)
а в TFProgressForm, по таймеру, обновляй состояние ProgressBar в соответствии с этой переменной.
Только  если TFProgressForm и долгая функция в разных потоках,а так и должно быть, - не забывай про синхронизацию  InterlockedIncrement

Ты обсуждение не читал видимо. То что ты написал я сделал раньше твоего поста, и это удобно только тем что не нужно нигде добавлять описание типа процедуры. В остальном такой вариант проигрывает процедуре. Процедура отдельная позволила избавится от постоянного повторения строк кода 
Код

AStep:=Round(100/steps);
  P1:=AStep*(Step-1);
  Max:=Max-Min;
  Progress:=Progress-Min;
  P2:=Round(Progress/(Max/AStep));
  ProgressBar1.Position:=P1+P2;
  ProgressBar1.Visible:=True;
  application.ProcessMessages;

во всех функциях, где я захочу работать с ProgressForm. 
Кроме того, таймер постоянно проверяющий состояние переменной будет доплонительной нагрузкой, а нафига, если можно обновлять и проверять состояние именно тогда, когда надо.

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

Это сообщение отредактировал(а) gesper - 28.5.2012, 01:31
--------------------
...И приколется обломившийся и oбломится приколовшийся...
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1130 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.