Перейти к содержанию
Fire Monkey от А до Я
  • 0

Возможно ли не использовать ProcessMessages в TAnimation?


krapotkin

Вопрос

TFloatAnimation использует ProcessMessages 

 

Это чревато возникновением всяких событий, и даже закрытию формы во время анимации, что приводит к AV

очень хочется иметь Repaint без ProcessMessages.

Это возможно?

Ссылка на комментарий

Рекомендуемые сообщения

  • 0
procedure TFmxObject.AnimateFloatWait(const APropertyName: string; const NewValue: Single; Duration: Single = 0.2;
  AType: TAnimationType = TAnimationType.atIn;
  AInterpolation: TInterpolationType = TInterpolationType.itLinear);
var
  A: TFloatAnimation;
begin
  StopPropertyAnimation(APropertyName);
  A := TFloatAnimation.Create(Self);
  try
    A.Parent := Self;
    A.AnimationType := AType;
    A.Interpolation := AInterpolation;
    A.Duration := Duration;
    A.PropertyName := APropertyName;
    A.StartFromCurrent := True;
    A.StopValue := NewValue;
    A.Start;
    while A.FRunning do
    begin
      Application.ProcessMessages;
      Sleep(0);
    end;
  finally
    A.DisposeOf;
  end;
end;

Мне нужно запустить анимацию формы: координаты, ширина, высота. Но окно  вспомогательное.

По задумке, если щелкнуть на него, оно должно исчезнуть. (и уничтожиться)

При неудачном стечении обстоятельств (форма удалилась во время анимации) получаем AV

Поэтому я запускаю 3 анимации как AnimateFloat и 4-ю AnimateFloatWait  чтобы нельзя было ее убить до завершения, и ...опять получаю AV

Разбираюсь - а она оказывается вовсю Processит Messages. В том числе и close...

Пробовал заменить весь метод ..Wait, искал к-нить аналог VCL Repaint. Но он не срабатывает.

Ссылка на комментарий
  • 0
  • Администраторы

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

 

Вместо них вы можете использовать любой аниматор и завершать его в момент разрушения формы.

Ссылка на комментарий
  • 0

но визуально работа указанных аниматоров будет проявляться только когда в главном потоке происходит ProcessMessages и там - обработка WM_PAINT. Принудительной прорисовки не будет.

Получается, если главный поток занят, то и анимация будет дерганая?

Я прав?

Ссылка на комментарий
  • 0
  • Администраторы

Да, вы правы.

 

При любом блокировании главного потока, будет происходит блокирование обработки сообщений - это базовый принцип работы настольных приложения для многих операционных систем. Анимация не будет дерганной, она просто полностью зависнет на время блокирования потока.

 

Однако, аниматор в FireMonkey не просто изменяет значение через указанные интервалы, а анализирует ситуацию с возможностью блокировки потока, и основывается на текущем времени. То есть, если анимация должна пройти за 4 секунды и началась в 0:00:00, а у вас на 1 секунду заблокировался основной поток, то анимация все равно закончится в 00:00:04. И будет задавать значение свойства таким, каким оно должно быть равно в момент времени t.

 

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

 

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

Application.ProcessMessage;

Однако, я не рекомендую этот способ, так как он может привести к другим неприятным последствиям.

 

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

Ссылка на комментарий
  • 0

Это базовая теория, и я в курсе её.

Давайте вернемся к исходной задаче. У меня нет фоновых операций. Мне нужно, чтобы именно анимация, именно в главном потоке доработала без прерываний. Нельзя использовать ProcessMessages! Ибо она обрабатывает ВСЕ виды событий. Мне всего лишь нужно, чтобы происходила только перерисовка. И лишь по окончанию анимации главный поток обрабатывал бы очередь сообщений дальше.

В VCL это достигается вызовом Repaint. В FMX - не работает.

Ссылка на комментарий
  • 0
  • Администраторы

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

 

Потом всплыли подробности использования, что вам нужно гарантировать, что форма не закроется в момент работы аниматоров. На нее тоже был дан ответ, что нужно использовать компоненты анимации и при закрытии формы проверять факт запущенных аниматоров. Или закрыть форму после завершения аниматоров в TAnimation.OnFinish.

 

Теперь третий уже вопрос, якобы исходная задача (смотрим на первый вопрос). Отдельно ответ на третий вопрос - можете использовать  

TForm.PaintRects
Ссылка на комментарий
  • 0

первый пост

>>TFloatAnimation использует ProcessMessages 

>>очень хочется иметь Repaint без ProcessMessages.

второй пост

>>я запускаю AnimateFloatWait  чтобы нельзя было ее убить до завершения, и ...опять получаю AV

>>Разбираюсь - а она оказывается вовсю Processит Messages.

>>искал к-нить аналог VCL Repaint.

 

TForm.PaintRects

а вот и ответ...

Ссылка на комментарий
Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...