如何在分层图像动画中停止闪烁

时间:2013-12-10 18:19:59

标签: delphi vcl

我使用30 png图片移植来制作一个简单的动画,一个Timer每33毫秒制作一个事件来改变具有png图像的TImage组件的可见性,我尝试了其他帖子中建议的所有方法停止闪烁,但无法解决问题。

unit Animation;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, AdvShaper, pngimage, ExtCtrls, StdCtrls;

type
  TAnimation_Form = class(TForm)
    Image1: TImage;
    Timer: TTimer;
    Image2: TImage;
    Image3: TImage;
    Image4: TImage;
    Image5: TImage;
    Image6: TImage;
    Image7: TImage;
    Image8: TImage;
    Image9: TImage;
    Image10: TImage;
    Image11: TImage;
    Image12: TImage;
    Image13: TImage;
    Image14: TImage;
    Image15: TImage;
    Image16: TImage;
    Image17: TImage;
    Image18: TImage;
    Image19: TImage;
    Image20: TImage;
    Image21: TImage;
    Image22: TImage;
    Image23: TImage;
    Image24: TImage;
    Image25: TImage;
    Image26: TImage;
    Image27: TImage;
    Image28: TImage;
    Image29: TImage;
    Image30: TImage;
    Exit: TButton;
    procedure TimerTimer(Sender: TObject);
    procedure ExitClick(Sender: TObject);
  private
    { Private declarations }
    Image_Counter:Integer;

    procedure ChooseImage(I:Integer);
    procedure Init();
  public
    { Public declarations }
  end;


procedure Run_Animation_Form();
procedure Finish_Animation_Form();

implementation
var
  Animation_Form: TAnimation_Form;
{$R *.dfm}

procedure Finish_Animation_Form();
Begin
  Animation_Form.Close;
End;

procedure Run_Animation_Form();

Begin
  Animation_Form := TAnimation_Form.Create(nil);
  Try
    Animation_Form.Init();
    Animation_Form.ShowModal();
  Finally
    Animation_Form.Free;
  End;
End;

{ TAnimation_Form }

procedure TAnimation_Form.ChooseImage(I: Integer);
begin
  TwinControl(FindComponent(Format('Image%d',[I]))).Visible := False;
  TwinControl(FindComponent(Format('Image%d',[I+1]))).Visible := True;
end;

procedure TAnimation_Form.ExitClick(Sender: TObject);
begin
  Close;
end;

procedure TAnimation_Form.Init;
begin
  TransparentColor := True;
  TransparentColorValue := Color;
  Image1.Visible := True;
  Image_Counter:=1;
  ControlStyle:=ControlStyle - [csOpaque];
  BorderWidth := 10;
  Anchors := [akLeft, akTop, akBottom, akRight];

end;

procedure TAnimation_Form.TimerTimer(Sender: TObject);
begin
  if Image_Counter >= 30 then
    Begin
      Image30.Visible := False;
      Image1.Visible := True;
      Image_Counter:=1;
    End
  else
    Begin
      ChooseImage(Image_Counter);
      Inc(Image_Counter);
    End;

end;

end.

感谢您的帮助,抱歉我的英语不好

1 个答案:

答案 0 :(得分:5)

我建议您创建一个包含30个TImage对象的数组,然后创建一个包含多个重叠Visible对象的多个TPNGImage对象,而不是使用它们:

  1. 使用始终可见的单个TImage,并在TImage.Picture过去时将所需的PNG分配给其TTimer属性:

    unit Animation;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, AdvShaper, pngimage, ExtCtrls, StdCtrls;
    
    type
      TAnimation_Form = class(TForm)
        Image1: TImage;
        Timer: TTimer;
        Exit: TButton;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure TimerTimer(Sender: TObject);
        procedure ExitClick(Sender: TObject);
      private
        { Private declarations }
        Image_Counter: Integer;
        Images: array[0..29] of TPNGImage;
      public
        { Public declarations }
      end;
    
    procedure Run_Animation_Form();
    procedure Finish_Animation_Form();
    
    implementation
    
    var
      Animation_Form: TAnimation_Form = nil;
    
    {$R *.dfm}
    
    procedure Finish_Animation_Form();
    Begin
      if Animation_Form <> nil then
        Animation_Form.Close;
    End;
    
    procedure Run_Animation_Form();
    Begin
      Animation_Form := TAnimation_Form.Create(nil);
      Try
        Animation_Form.ShowModal();
      Finally
        FreeAndNil(Animation_Form);
      End;
    End;
    
    { TAnimation_Form }
    
    procedure TAnimation_Form.FormCreate(Sender: TObject);
    var
      I: Integer;
    begin
      for I := Low(Images) to High(Images) do
      begin
        Images[I] := TPNGImage.Create;
        // load PNG image into Images[I] as needed...
      end;
    
      // FYI, these properties can be set at design time...
      TransparentColor := True;
      TransparentColorValue := Color;
      Image1.Visible := True;
      BorderWidth := 10;
      Anchors := [akLeft, akTop, akBottom, akRight];
    
      Image_Counter := 0;
      Image1.Picture := Images[0];
    
      ControlStyle := ControlStyle - [csOpaque];
    end;
    
    procedure TAnimation_Form.FormDestroy(Sender: TObject);
    var
      I: Integer;
    begin
      for I := Low(Images) to High(Images) do
        Images[I].Free;
    end;
    
    procedure TAnimation_Form.ExitClick(Sender: TObject);
    begin
      Close;
    end;
    
    procedure TAnimation_Form.TimerTimer(Sender: TObject);
    begin
      Inc(Image_Counter);
      if Image_Counter > High(Images) then
        Image_Counter := 0;
      Image1.Picture := Images[Image_Counter];
    end;
    
    end.
    
  2. 使用单个TPaintBox并为其指定一个OnPaint事件处理程序,将当前PNG绘制到TPaintBox.Canvas上,然后让TTimer更新当前的PNG并调用TPaintBox.Invalidate()来触发重绘:

    unit Animation;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, AdvShaper, pngimage, ExtCtrls, StdCtrls;
    
    type
      TAnimation_Form = class(TForm)
        PaintBox1: TPaintBox;
        Timer: TTimer;
        Exit: TButton;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure TimerTimer(Sender: TObject);
        procedure ExitClick(Sender: TObject);
        procedure PaintBox1Paint(Sender: TObject);
      private
        { Private declarations }
        Image_Counter: Integer;
        Images: array[0..29] of TPNGImage;
      public
        { Public declarations }
      end;
    
    procedure Run_Animation_Form();
    procedure Finish_Animation_Form();
    
    implementation
    
    var
      Animation_Form: TAnimation_Form = nil;
    
    {$R *.dfm}
    
    procedure Finish_Animation_Form();
    Begin
      if Animation_Form <> nil then
        Animation_Form.Close;
    End;
    
    procedure Run_Animation_Form();
    Begin
      Animation_Form := TAnimation_Form.Create(nil);
      Try
        Animation_Form.ShowModal();
      Finally
        FreeAndNil(Animation_Form);
      End;
    End;
    
    { TAnimation_Form }
    
    procedure TAnimation_Form.FormCreate(Sender: TObject);
    var
      I: Integer;
    begin
      for I := Low(Images) to High(Images) do
      begin
        Images[I] := TPNGImage.Create;
        // load PNG image into Images[I] as needed...
      end;
    
      // FYI, these properties can be set at design time...
      TransparentColor := True;
      TransparentColorValue := Color;
      Image1.Visible := True;
      BorderWidth := 10;
      Anchors := [akLeft, akTop, akBottom, akRight];
    
      Image_Counter := 0;
    
      ControlStyle := ControlStyle - [csOpaque];
    end;
    
    procedure TAnimation_Form.FormDestroy(Sender: TObject);
    var
      I: Integer;
    begin
      for I := Low(Images) to High(Images) do
        Images[I].Free;
    end;
    
    procedure TAnimation_Form.ExitClick(Sender: TObject);
    begin
      Close;
    end;
    
    procedure TAnimation_Form.TimerTimer(Sender: TObject);
    begin
      Inc(Image_Counter);
      if Image_Counter > High(Images) then
        Image_Counter := 0;
      PaintBox1.Invalidate;
    end;
    
    procedure TAnimation_Form.PaintBox1Paint(Sender: TObject);
    begin
      PaintBox1.Canvas.Draw(0, 0, Images[Image_Counter]);
      // or:
      // PaintBox1.Canvas.StretchDraw(Rect(0, 0, PaintBox1.Width, PaintBox1.Height), Images[Image_Counter]);
    end;
    
    end.