在Delphi多设备应用程序中为我的例程添加延迟或休眠

时间:2015-01-26 14:34:20

标签: delphi firemonkey delphi-xe7

使用Dephi XE-7和FMX(多设备应用程序) - 当前在Win32中进行编译

我正在使用Raize Radiant Shapes并尝试创建一个演示,我可以遍历所有RadiantCircles并更改其笔触和填充颜色。我的屏幕上有四个垂直排列的RadiantCircles。下面的代码有效,但速度很快。如何在每次迭代后添加“延迟”,“睡眠”,“等”以减慢速度。似乎AnimateColor会影响我的延迟。

var
 I: integer;
 fillColor: Cardinal;


for I := 0 to ScaledLayout2.ControlsCount-1 do
 if ScaledLayout2.Controls[I] is TRadiantCircle then
 begin
   TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Stroke.Color', 4294967040, 1); //yellow
   case  TRadiantCircle(ScaledLayout2.Controls[I]).Tag of
    1: fillColor:= 4278190335; //Blue
    2: fillColor:= 4281519410; //Lime Green
    3: fillColor:= 4294901760; //Red
    4: fillColor:= 4293821166; //Dark Violet
   end;
   TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Fill.Color', fillColor, 1);
   TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Stroke.Color', 4278190080, 1); //black
   case TRadiantCircle(ScaledLayout2.Controls[I]).Tag of
    1: fillColor:= 4278190219; //Dark Blue
    2: fillColor:= 4278215680; //Dark Green
    3: fillColor:= 4287299584; //Dark Red
    4: fillColor:= 4286578816; //Purple
   end;
   TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Fill.Color', fillColor, 1);
  sleep(1000);
 end;

我尝试在每次迭代结束后放置一个sleep(1000),但它不起作用。我根本无法看到动画。睡眠是多设备应用程序的当前功能吗?

1 个答案:

答案 0 :(得分:1)

在文章中你提到过你一直在考虑使用计时器,但无法弄清楚如何做到这一点。

简而言之,将更新代码(循环内部的代码)转换为接受索引作为参数的单独程序。 然后在计时器OnTimer事件中,您需要注意增加该索引并执行如下所示的方法:

procedure TMyForm.MyAnimation(I: Integer);
begin
  if ScaledLayout2.Controls[I] is TRadiantCircle then
  begin
    TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Stroke.Color', 4294967040, 1); //yellow
    case  TRadiantCircle(ScaledLayout2.Controls[I]).Tag of
      1: fillColor:= 4278190335; //Blue
      2: fillColor:= 4281519410; //Lime Green
      3: fillColor:= 4294901760; //Red
      4: fillColor:= 4293821166; //Dark Violet
    end;
    TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Fill.Color', fillColor, 1);
    TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Stroke.Color', 4278190080, 1); //black
    case TRadiantCircle(ScaledLayout2.Controls[I]).Tag of
      1: fillColor:= 4278190219; //Dark Blue
      2: fillColor:= 4278215680; //Dark Green
      3: fillColor:= 4287299584; //Dark Red
      4: fillColor:= 4286578816; //Purple
    end;
    TRadiantCircle(ScaledLayout2.Controls[I]).AnimateColor('Fill.Color', fillColor, 1);
  end;
end;

procedure TMyForm.Timer1Timer(Sender: TObject);
begin
  //Check to see if we already reached end of animation
  if ComponentIndex > AnimationLength do
  begin
    //Reset component index back to 0 so we can repeat hte animation if required
    ComponentIndex  := 0;
    //Disable the timer
    Timer1.Enabled := False;
  end
  //if not continue with animation
  else
  begin
    //Execute MyAnimation for specific component defined by its index
    MyAnimation(ComponentIndex );
    //Increase the ComponentIndex by one which means that next time the Timer fires we advance with our animation
    ComponentIndex := ComponentIndex +;
end;

所以你基本上通过启用计时器开始这个动画,一旦动画到达结束它就会禁用计时器并将I设置为0,所以它基本上重置为初始位置。

如果你需要多个concurent动画,你需要多个定时器,所以在需要时在运行时创建它们然后在动画结束时最终破坏它们可能不是一个坏主意。

另外,您可以查看下一个链接,了解如何在Delphi中收集各种动画: http://docwiki.embarcadero.com/CodeExamples/XE7/en/FMXTimerAnimation_(Delphi)

编辑:至于解释为什么使用睡眠不起作用: 当您在代码中使用Sleep命令时,它所执行的操作将停止执行从中指定的特定毫秒毫秒调用它的线程。

因此,当您从用于UI更新的主线程中调用Sleep时,您实际上会停止该特定时间的UI更新,并且通过操作来阻止您的程序将UI更新为当前状态。

这就是为什么你的动画会出现这种情况,但你会立即获得最终结果。

现在,为了让它按您的意愿工作,您必须强制程序UI在调用Sleep之前自行更新。

你可以通过调用Application.ProcessMessages来实现这一点,但我不会这样做,因为它可能带来很多其他问题。