2012-12-06 51 views
4

使用Delphi XE2我想让一些按钮在delphi应用程序中移动。delphi中的双缓冲区

我写了这个代码:

procedure TForm1.DoSomething; 
var x : integer; 
begin  
    for x := 200 downto 139 do begin 
     // move two buttons 
     Button1.Top := x; 
     Button3.Top := x; 
     // skip some repaints to reduce flickering 
     if (x mod 7 = 1) then begin 
      Form1.Repaint; 
     Sleep(50); 
    end; 
end; 

不幸的是运行此程序时,它仍然显著闪烁。

这里是我的问题: 有什么办法可以使动画平滑(没有任何闪烁)?

编辑: 为了使动画更加流畅,改变50的东西在睡眠(50)更小,并删除这一行:

if(x mod 7 = 1) then begin 

回答

3

设置Form1.DoubleBufferedTrue。你可以在代码中做到这一点,但我认为这个属性是在XE2中发布的,所以你可以在Object Inspector中设置它。

+1

如此强大的财产。谢谢,我会在10分钟后以接受的方式打勾 –

+1

是的,但一个财产很容易导致令人讨厌的视觉怪癖。 –

+0

@DavidHeffernan绝对是不错的选择,如果你可以在没有使用双缓冲的情况下找到重绘闪烁的方法,那么试着去做。从我自己的经验,并如大卫指出,双缓冲往往导致一些视觉问题,如按钮周围的黑边等。 – 2012-12-07 19:49:01

2

我发现决定多长时间需要运动取代使用睡眠过程会更好。这可以更好地适应不同速度的电脑,并且还可以针对不同的距离进行调整。如果您希望在屏幕上移动1秒钟,则需要在重新绘制之间移动较小的步幅,而仅需花费0.5秒来移动屏幕。

我不记得确切的原因,但我们也添加了代码重新绘制父。我认为当我们的对象在屏幕上移动时,我们遇到了鬼影留下的问题。

这是我们正在使用的代码。这是在一个可以在屏幕上移动和移出的组件内部。

procedure TMyObject.ShiftRight; 
var 
    TicksStart: int64; 
    StartLeftValue: integer; 
    EndLeftValue: integer; 
    NewLeftValue: integer; 
    LeftValueDif: integer; 
    RemainingTicks: int64; 

begin 
    StartLeftValue := Self.Left; 
    EndLeftValue := Self.Left + Self.Width; 
    LeftValueDif := EndLeftValue - StartLeftValue; 

    TicksStart := GetTickCount(); 
    RemainingTicks := FadeTime; // Fade Time is a constants that dermines how long the 
           // slide off the screen should take 

    while RemainingTicks > 0 do 
    begin 
    NewLeftValue := (LeftValueDif * (FadeTime - RemainingTicks)) div FadeTime; 
    Self.Left := Max(StartLeftValue, NewLeftValue); 
    Self.Parent.Repaint; 
    Self.Repaint; 

    RemainingTicks := FadeTime - int64(GetTickCount - TicksStart); 
    end; 

    if Self.Left < EndLeftValue then 
    Self.Left := EndLeftValue; 

    Self.Parent.Repaint;  
    Self.Repaint; 
end; 
+0

我也注意到,睡眠使得应用程序在不同的计算机上随机工作。无论如何,感谢您的反馈。 –

+1

这确实是一种常用的方法:计算物体在当前时间点的位置。不过,我也怀疑这两次重绘。实际上,我想我会选择不这样做,因为这会在循环运行时阻塞应用程序。相反,我想我会使用计时器,将循环的内部放入其OnTimer事件中,并使用Self.Invalidate请求重绘。它将允许快速用户立即继续工作,而无需等待动画完成。 – GolezTrol