2012-12-06 53 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