Delphi中的双缓冲技术

4
使用Delphi XE2,我想让一些按钮在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;

很不幸,在运行此过程时仍会出现明显的闪烁。

我的问题是: 有没有办法使动画更加平滑(没有任何闪烁)?

编辑: 为了使动画更加平滑,在sleep(50)中将50更改为更小的数字,并删除此行:

if(x mod 7 = 1) then begin
2个回答

4

Form1.DoubleBuffered设置为True。您可以通过代码实现,但我认为该属性已在XE2中发布,因此您也可以在“对象检查器”中进行设置。


1
如此强大的属性。谢谢,我会在10分钟后标记为已接受。 - Jack L.
1
是的,但这个属性可能会导致不良的视觉瑕疵。 - David Heffernan
@DavidHeffernan 绝对是正确的,如果你能找到一种不使用双缓冲技术就能实现无闪烁重绘的方法,那么请尝试使用它。从我的经验来看,正如David所指出的,双缓冲技术经常会导致一些视觉问题,比如按钮周围出现暗边等。 - user1175743

2
我发现,与使用Sleep过程相比,最好决定需要移动多长时间,这样可以更好地适应不同速度的计算机,并适应不同的移动距离。如果您想在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;

我也注意到睡眠会导致不同电脑上的应用程序随机工作。无论如何,感谢您的反馈。 - Jack L.
1
这确实是一种常见的方法:计算对象在当前时间点应该在哪里。不过我也对两个重绘有疑问。实际上,我认为我不会像这样在循环中执行此操作,因为它会在循环运行时阻塞应用程序。相反,我会使用定时器,将循环内部放入其OnTimer事件中,并使用Self.Invalidate请求重绘。这将允许快速用户立即继续工作,而无需等待动画完成。 - GolezTrol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接