QWorker演示-正余弦曲线动态绘制示例解析

 

这个示例主要是演示了Delay函数的用法,示例中用Delay来作一个延迟作业,在每次作业时绘制一段曲线,从而形成动态效果。

程序运行最终的效果如图所示:

首先,我们放置了一个TChart对象,并预定义了两个TLineSeries类型的图表项目,我们在操作时,以线来拟合成正余弦曲线。

当我们点击开始按钮时,我们触发了下面的代码:

procedure TForm6.Button1Click(Sender: TObject);
begin
slCos.Clear;
slSin.Clear;
FFlags := 0;
Button1.Enabled:=False;
if CheckBox1.Checked then
  begin
  Chart1.LeftAxis.SetMinMax(-1, 1);
  Chart1.BottomAxis.SetMinMax(0, 10);
  end
else
  begin
  Chart1.LeftAxis.Automatic:=True;
  Chart1.BottomAxis.Automatic:=True;
  end;
//牵涉到VCL的控件,这两个作业必需在主线程中执行
Workers.Delay(DoSinJob, Q1MillSecond * 50, Pointer(0), True);
Workers.Delay(DoCosJob, Q1MillSecond * 50, Pointer(0), True);
end;

为了可以重复点击演示,我们先清除了上次的slCos和slSin两条线图的内容,然后设置标志为0,我们定义FFlags是为了确定何时可以重新启用Button1这个按钮,再次点击。CheckBox1是否选择固定坐标范围选项。然后我们分别延迟50ms计划了两个作业DoSinJob和DoCosJob,每次作业只添加一个新的数据点。为了方便,我们直接利用了作业的Data成员来记录上次作业已经进行到第几步,所以这里初始为0。这里要注意ARunInMainThread参数必需设置为True。这是因为我们在这个演示中,在作业中要添加结点时,要操作Chart1这个VCL控件,而VCL不是线程安全的,所以必需在主线程中执行这个作业。

剩下的就是DoSinJob和DoCosJob两个作业了,我们简单看下代码:

procedure TForm6.DoCosJob(AJob: PQJob);
var
  V: Double;
begin
V := Integer(AJob.Data) / 10;
slCos.AddXY(V, cos(V));
//如果绘制未完成,再次延迟触发下一次绘图
if Integer(AJob.Data) < 100 then
  Workers.Delay(DoCosJob, Q1MillSecond * 50,
    Pointer(Integer(AJob.Data) + 1), True)
else//设置并检查是否两个作业都完成了,如果完成了,更新按钮状态
  begin
  FFlags := FFlags or $01;
  if FFlags = $03 then
    Button1.Enabled := True;
  end;
end;
 
procedure TForm6.DoSinJob(AJob: PQJob);
var
  V: Double;
begin
V := Integer(AJob.Data) / 10;
slSin.AddXY(V, sin(V));
//如果绘制未完成,再次延迟触发下一次绘图
if Integer(AJob.Data) < 100 then
  Workers.Delay(DoSinJob, Q1MillSecond * 50,
    Pointer(Integer(AJob.Data) + 1), True)
else//设置并检查是否两个作业都完成了,如果完成了,更新按钮状态
  begin
  FFlags := FFlags or $02;
  if FFlags = $03 then
    Button1.Enabled := True;
  end;
end;

在这里,我们将AJob.Data转换为整数后,然后除以10来得到实际的步进值。当后面再次计算下一次作业时,这个值加了1,也就是说,实际的步长是0.1。在执行100次调用后,我们设置并检查最终的标志位,在检测到两个都完成后,Button1重新启用。如果执行次数小于100次,则再次调用Delay延迟50ms计划下一次调用。最终就形成了50ms/帧的动态演示效果。

delaydemo

 

分享到: