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



我在一个移植自上使用了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.

谢谢你的帮助,很抱歉我的英语不好

与其使用多个重叠的TImage对象并交换它们的Visible属性,我建议您创建一个由30个TPNGImage对象组成的数组,然后:

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

    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.
    

最新更新