[教程] ZValueWatch 教程之二:在线程中处理图片

前面的教程中,我们演示了一个进度更新和位置调整的示例,接下来我们演示如何创建一个特定类型的监视对象来动态更新一个特殊类型的属性。

1、在界面上放置需要的组件,我们要在线程中动态更新图像内容,然后在前台显示(本示例依赖于 Graphics32)。

TForm1 = class(TForm)
    Panel1: TPanel;
    Image1: TImage;
    SpeedButton1: TSpeedButton;
    Panel2: TPanel;
    ZWatcher1: TZWatcher;
    procedure SpeedButton1Click(Sender: TObject);
  private
    { Private declarations }
    FThread: TThread;
    FImageWatch: IZValueWatch<TBitmap32>;
  public
    { Public declarations }
  end;

2、设置 ZWatcher的Kind为wkMessage或 wkTimer。

3、创建一个 TPictureWatch 类型的监视类定义,重载 DoSetValue 函数,来设置目标缓存的值,代码如下:

type
  TPictureWatch = class(TZObjectWatchItem<TBitmap32>)
  protected
    procedure DoSetValue(var ATarget: TBitmap32;
      const ANewValue: TBitmap32); override;
  public
  end;
implementation

procedure TPictureWatch.DoSetValue(var ATarget: TBitmap32;
const ANewValue: TBitmap32);
begin
  if not Assigned(ATarget) then
    ATarget := TBitmap32.Create(ANewValue.Width, ANewValue.Height);
  ATarget.Assign(ANewValue);
end;

initialization

TZWatchItems.Register<TBitmap32>(TPictureWatch);

4、在 SpeedButton1 的 OnClick 事件中,我们加入相应的代码:

if not Assigned(FImageWatch) then
    FImageWatch := TZWatchItems.Current.CreateWatch<TBitmap32>(
      procedure(const ABitmap: TBitmap32)
      begin
        Image1.Picture.Assign(ABitmap);
      end);
  SpeedButton1.Enabled := false;
  FThread := TThread.CreateAnonymousThread(
    procedure
    var
      ABitmap: TBitmap32;
    begin
      ABitmap := TBitmap32.Create(200, 100);
      try
        while not Application.Terminated do
        begin
          ABitmap.FillRect(0, 0, 200, 100, clWhite32);
          for var I := 0 to 9 do
          begin
            ABitmap.FrameRectS(I * 10, I * 5, 200 - I * 10, 100 - I * 5,
              Color32(255 * I div 10, 255 * I div 10, 255 * I div 10, 255));
            if not Application.Terminated then
              FImageWatch.Value := ABitmap
            else
              break;
            Sleep(50);
          end;
        end;
      finally
        FreeAndNil(ABitmap);
        TThread.Queue(nil,
          procedure
          begin
            SpeedButton1.Enabled := true;
            FreeAndNil(FThread);
          end);
      end;
    end);
  FThread.Start;

我们创建了 FImageWatch,并在后台线程中,直接访问并对它的 Value 进行了赋值操作。

我们在线程的图像处理代码中,创建了一个 TBitmap32 对象的实例,并对其进行绘制,每隔50ms更新一帧,保持约 20 fps 的刷新速度。

5、完成,我们看下程序运行效果:

分享到: