2012-12-06 5 views
4

Delphi XE2를 사용하여 델파이 애플리케이션에서 몇 가지 버튼을 이동시키고 싶었습니다. 이 절차를 실행할 때델파이의 더블 버퍼링

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은 이중 버퍼링을 사용하지 않고 깜박임없이 다시 칠할 수있는 방법을 찾은 다음 시도해보십시오. 내 자신의 경험에서, 그리고 데이비드 더블 버퍼링을 지적 자주 버튼 주위 어두운 가장자리와 같은 몇 가지 시각적 문제로 이어집니다. –

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