2017-06-22 77 views
0

好吧,问题可能不是可以解决的,但它真的困扰我。我做了一个简单的程序,它有三个菜单,并使用计时器来移动菜单的左右。当我将图像(菜单)移动到屏幕的左侧(使image.left为负数时),这使得这个奇怪的小故障,我不知道是什么造成它,虽然图像(菜单)的质量非常高,如果是这样的原因....我能做些什么德尔福图像运动故障

注:在Delphi

业余这是我

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.  
+2

你不应该为图像移动动画移动控件。你应该画在画布上。有一个定时器可以更新内部存储的坐标(针对每个图形对象),并将为包含该画布的控件(例如'TPaintBox')调用“Invalidate”。剩下的就是通过这些坐标在该画布上绘制图形。 – Victoria

+0

谢谢你的帮助。我研究过TPaintBox,这是一个非常有趣的概念,不幸的是,与我真正想创建的相比,我所看到的有一些局限性。我试图在这里实现的是创建一个时尚的UI,它具有平移过渡效果,如在选择菜单选项卡时,它水平滑动到该菜单部分。我的用户界面主要是图像,前景中的按钮不可见。我可能低估了TPaintBox的功能,如果我能,请你进一步解释一下这个实现 – loskiTheMachine

回答

1

你永远不会实现平稳从计时器和/ o驱动动画时的任何类型的动画依靠Windows控件作为你的“精灵”。

Delphi中的标准计时器组件使用基于Windows消息的计时器事件,这意味着这些事件的处理依赖于您的UI线程的消息处理,该线程还处理鼠标移动,绘画和其他整个主机消息需要保持你的UI响应。

定时器消息采用绝对最低优先级。

同样,windows控件的设计目的是管理与用户的交互。动画和效果可以用作该交互的一部分,但是系统并未针对在屏幕上移动控件进行优化,因为这对于UI控件来说是非常不寻常的行为。

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

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

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

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

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

为了提高效率,如果您的窗体/应用程序中有多种以这种方式进行动画制作的控件,通常可以使用单个线程将绘制消息发布到所有必需的控件。