前面的教程中,我们演示了一个进度更新和位置调整的示例,接下来我们演示如何创建一个特定类型的监视对象来动态更新一个特殊类型的属性。
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、完成,我们看下程序运行效果: