德尔福图像运动故障

时间:2017-06-22 17:04:03

标签: image delphi

好吧,这个问题可能无法解决,但它确实困扰着我。我做了一个简单的程序,有三个菜单,并使用计时器左右移动菜单。

问题出现在我将图像(菜单)移动到屏幕左侧(使图像。左侧为负。这会产生这种奇怪的故障,white blocks that show up out of nowhere。我不确定是什么导致它虽然图像(菜单)的质量非常高,但如果这是原因......我该怎么办?

NB:德尔福的业余爱好者

这就是我所拥有的

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    pnl1: TPanel;
    tmr1: TTimer;
    btn1: TButton;
    pnl2: TPanel;
    pnl3: TPanel;
    btn2: TButton;
    btn3: TButton;
    tmr2: TTimer;
    tmr3: TTimer;
    img1: TImage;
    img2: TImage;
    img3: TImage;
    img4: TImage;
    pnlmain: TPanel;
    shp1: TShape;
    procedure btn1Click(Sender: TObject);
    procedure tmr1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btn2Click(Sender: TObject);
    procedure tmr2Timer(Sender: TObject);
    procedure btn3Click(Sender: TObject);
    procedure tmr3Timer(Sender: TObject);
  private
    { Private declarations }
    iBar : Integer;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btn1Click(Sender: TObject);
begin
 tmr1.Enabled := True;
 btn1.Enabled := False;
 btn2.Enabled := true;
 btn3.Enabled := true;
end;

procedure TForm1.tmr1Timer(Sender: TObject);
begin
  if iBar = 1 then
  begin
  if pnl2.Left <> 70 then
  begin
  pnl1.Left := pnl1.Left-72;
  pnl2.Left := pnl2.Left-72;
  pnl3.Left := pnl3.Left-72;
  end
  else
  begin
     pnl1.Left := pnl1.Left-70;
     pnl2.Left := pnl2.Left-70;
     pnl3.Left := pnl3.Left-70;
     iBar := 2;
     tmr1.Enabled := False;
  end;
  end;

  if iBar = 3 then
  begin
     if pnl2.Left <> -70 then
     begin
     pnl3.Left := pnl3.Left+72;
     pnl2.Left := pnl2.Left+72;
     pnl1.Left := pnl1.Left+72;
     end
     else
     begin
     pnl3.Left := pnl3.Left+70;
     pnl2.Left := pnl2.Left+70;
     pnl1.Left := pnl1.Left+70;
     iBar := 2;
     tmr1.Enabled := False;
     end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 iBar := 1;
end;

procedure TForm1.btn2Click(Sender: TObject);
begin
  tmr2.Enabled := true;
  btn2.Enabled := False;
  btn1.Enabled := true;
  btn3.Enabled := true;
end;

procedure TForm1.tmr2Timer(Sender: TObject);
begin
  if iBar = 3 then
  begin
  if pnl1.Left <> -140 then
  begin
     pnl3.Left := pnl3.Left+144;
     pnl1.Left := pnl1.Left+144;
     pnl2.Left := pnl2.Left+144;
  end
  else
  begin
     pnl3.Left := pnl3.Left+140;
     pnl1.Left := pnl1.Left+140;
     pnl2.Left := pnl2.Left+140;
     iBar := 1;
     tmr2.Enabled := False;
  end;
  end;

  if iBar = 2 then
  begin
     if pnl1.Left <> -70 then
     begin
     pnl2.Left := pnl2.Left+72;
     pnl1.Left := pnl1.Left+72;
     pnl3.Left := pnl3.Left+72;
     end
     else
     begin
     pnl2.Left := pnl2.Left+70;
     pnl1.Left := pnl1.Left+70;
     pnl3.Left := pnl3.Left+70;
     iBar := 1;
     tmr2.Enabled := False;
       end;
  end;
end;

procedure TForm1.btn3Click(Sender: TObject);
begin
 tmr3.Enabled := True;
 btn3.Enabled := False;
 btn2.Enabled := true;
 btn1.Enabled := true;
end;

procedure TForm1.tmr3Timer(Sender: TObject);
begin
  if iBar = 1 then
  begin
  if pnl3.Left <> 140 then
  begin
     pnl1.Left := pnl1.Left-144;
     pnl3.Left := pnl3.Left-144;
     pnl2.Left := pnl2.Left-144;
  end
  else
  begin
     pnl1.Left := pnl1.Left-140;
     pnl3.Left := pnl3.Left-140;
     pnl2.Left := pnl2.Left-140;
     iBar := 3;
     tmr3.Enabled := False;
       end;
  end;

  if iBar = 2 then
  begin
     if pnl3.Left <> 70 then
     begin
     pnl2.Left := pnl2.Left-72;
     pnl3.Left := pnl3.Left-72;
     pnl1.Left := pnl1.Left-72;
     end
     else
     begin
     pnl2.Left := pnl2.Left-70;
     pnl3.Left := pnl3.Left-70;
     pnl1.Left := pnl1.Left-70;
     iBar := 3;
     tmr3.Enabled := False;
       end;
  end;
end;

end.    

1 个答案:

答案 0 :(得分:1)

从定时器驱动动画和/或依靠Windows控件作为“精灵”时,您永远无法实现任何排序的平滑动画。

Delphi中的标准计时器组件使用基于Windows消息的计时器事件,这意味着这些事件的处理依赖于UI线程的消息处理,这也处理鼠标移动,绘制和一大堆其他消息需要保持您的UI响应。

计时器消息的优先级最低。

同样,Windows控件旨在管理与用户的交互。动画和效果可用作该交互的一部分,但系统未针对屏幕周围的物理移动控件进行优化,因为这对于UI控件来说是极不寻常的行为。

您可能还记得一些较旧的Windows“笑话”程序,其中有一个消息框,当您尝试点击它时,“确定”按钮会在屏幕上跳转...?移动的控件通常比有用更烦人。

以这种方式制作动画可以作为概念证明或原型放在用户面前以获得反馈,但是你总会遇到你描述的那种“故障”。

对于您的“生产”代码,您应该重新考虑您的UI实现。

如果你真的需要动画菜单,那么设计并实现一个控件,将其作为单个控件中的行为来实现。

在后台线程上管理该控件中元素的动画(即更新元素位置的“模型”)。为了渲染每个“框架”,专门组合一个单独的线程来向控件发布消息,以便根据实现流畅动画的需要频繁地绘制自己,这幅画是唯一必须与所有其他UI消息一致操作的代码。应用正在处理。

作为效率改进,如果您在表单/应用程序中以这种方式设置了多个控件,则通常可以使用单个线程将该消息消息发布到所有必需的控件。