Как дождаться завершения TTimer?

У меня есть TFrame (fraDisplay) с TTimer (timAnimateDataChange). Таймер используется для управления небольшой анимацией. В форме, содержащей фрейм, я хочу иметь метод, который делает что-то вроде этого:

procedure TForm.DoStuff;
begin
   DoSomeLogicStuff;
   fraDisplay.AnimateResult;
   WaitForAnimationToFinish;
   DoSomeOtherLogicStuff;
   fraDisplay.AnimateEndResult;
   WaitForAnimationToFinish;
   fraDisplay.Finalize;
end;

Анимации в основном представляют собой перерисовку TImage32, синхронизированную с таймером. Таймер отключится сам после завершения, а у кадра есть логическое свойство AnimationRunning, которое будет установлено в false, когда анимация будет завершена.

Нет нитей или чего-то подобного, чтобы усложнить или помочь делу.

Вопрос в том, как реализовать метод WaitForAnimationToFinish?

(Кстати, это не очень хорошее решение:

procedure TForm.WaitForAnimationToFinish;
begin
  repeat 
    Application.ProcessMessages;
  until not fraDisplay.AnimationRunning;
end;

так как таймер не сработает во время работы метода :-()


person Svein Bringsli    schedule 22.11.2009    source источник


Ответы (5)


Предложение Smasher можно реализовать с помощью Анонимные методы Delphi 2009.

procedure TForm.DoStuff;
begin
  DoSomeLogicStuff;
  fraDisplay.AnimateResult.OnFinished := 
    procedure (Sender: TObject)
    begin
      DoSomeOtherLogicStuff;
      fraDisplay.AnimateEndResult.OnFinished := 
        procedure (Sender: TObject)
        begin
          fraDisplay.Finalize;
        end;
      fraDisplay.AnimateEndResult;
    end;
  fraDisplay.AnimateResult;
end;

Кстати: на самом деле, WaitForAnimationToFinish позволит OnTimer сработать, поскольку он использует сообщения Windows, которые отправляются при вызове ProcessMessages. Но в любом случае это плохая идея, поскольку она использует много ресурсов ЦП, на самом деле не нуждаясь в этом.

person Lars Truijens    schedule 22.11.2009
comment
Звучит как хорошее предложение. К сожалению, я все еще на 2007 :-( (во всяком случае, еще на пару месяцев) - person Svein Bringsli; 22.11.2009
comment
Это также работает без анонимных методов. Тогда просто нужно немного больше кода :) - person Lars Truijens; 22.11.2009

Когда таймер отключится и установит для переменной AnimationRunning значение False, вы можете просто вызвать метод, который должен выполняться следующим.

person jpfollenius    schedule 22.11.2009
comment
Я не знаю, какой метод следует вызывать следующим. Существует несколько методов, которые требуют паузы и ожидания завершения анимации. - person Svein Bringsli; 22.11.2009

Товарищ словенский программист Delphi написал именно тот код, который вам нужен — Активный сон.

person gabr    schedule 23.11.2009

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

Пока вы ожидаете окончания анимации (если бы могли), остальная часть вашего приложения будет вести себя как мертвая программа, т.е. она никак не будет реагировать на GUI, включая изменение размера, перерисовку, закрытие с помощью X и т. д.

Решение состоит в том, чтобы вместо этого разбить метод DoStuff на два; один запускает действие таймера, а второй выполняется, когда таймер заканчивается. Чтобы выполнить последнее, этот таймер должен вызывать ваш второй метод непосредственно перед прощанием.

Ларс проделал большую работу по составлению примера; Считай, что эта книга подойдет к его фильму :)

person Carl Smotricz    schedule 22.11.2009
comment
Не ужасно долго. Секунду или около того. На самом деле это небольшая реализация монополии. Анимация — это такие вещи, как анимация броска кубика, перемещение жетонов и т. д. Здесь нет причудливой графики, только текст и цветные прямоугольники на холсте, но определенное количество анимации делает игру более приятной. У меня есть один объект, названный TGame, у которого есть свойство FDisplay, которое является кадром, о котором я упоминал. Фрейм имеет такие методы, как AnimateDieRoll и MoveToken. - person Svein Bringsli; 22.11.2009

Заставьте AnimateResults принимать параметр метода, который будет вызываться по завершении.

person Loren Pechtel    schedule 22.11.2009