2013-12-11 5 views
0

버튼을 클릭 한 후 그림 1을 화면 상단으로 이동시키는 코드를 작성해야합니다. pictire1이 화면의 상단 20 픽셀에 도달하면 보이지 않게되고 picture2를 볼 수있게해야합니다. 이것은 내 잘못된 코드입니다 :C#의 동영상 이동

private void button1_Click(object sender, EventArgs e) 
{ 
    int b = pictureBox1.Top; 

    for (int i = b; i < 20; i--) 
    { 
     pictureBox1.Top = i; 
     System.Threading.Thread.Sleep(20); 
    } 

    if (pictureBox1.Top < 20) 
    { 
     pictureBox1.Visible = false; 
     pictureBox2.Visible = true; 
    } 
} 

어떤 아이디어를 고칠 수 있습니까? pictureBox1.Top 할당, 호출 후

+7

그것의 어느 부분이 잘못 되었습니까? 그것이 어떻게 행동 할 것이라고 기대되는 것과 비교하면 지금 어떻게 행동하고 있습니까? –

+0

오류가 없으며 작동하지 않습니다. 버튼을 클릭해도 아무런 변화가 없습니다. – Noterezeck

+0

디버깅 프로세스의 일부로 코드를 밟았습니까? 지금은 누구나 추측 할 수 있습니다. 이 이벤트 처리기가 전혀 실행되지 않을 수도 있습니다. 처음 시작했을 때 맞았는지 확인한 후 단계별로 진행하고 모든 정수 값을 확인하십시오. –

답변

3

이 잘못된 것 같다 : 이것은 루프 i < 20 동안 것

for (int i = b; i < 20; i--) 
{ 
    pictureBox1.Top = i; 
    System.Threading.Thread.Sleep(20); 
} 

. 그러나 코드에서 Top == 20에 도달하면 다른 그림을 보여주고 싶다는 것을 알 수 있습니다. 그래서 나는 i >= 20이어야하고 ifTop <= 20이어야한다고 생각합니다.

또한 디스플레이를 새로 고침하지 않습니다. 루프와 Sleep으로 인해 UI 업데이트가 없습니다. Cobra_Fast에서 알 수 있듯이

이 추가하기 전에 Sleep :

this.Invalidate(); 
this.Refresh(); 

, 다음 (나는 또한 약간 명확하게하기 위해 코드를 수정 한) 작업을해야 그것을 요약하면 :

private void button1_Click(object sender, EventArgs e) 
{ 
    while (pictureBox1.Top >= 20) 
    { 
     pictureBox1.Top = pictureBox1.Top - 1; 
     this.Invalidate(); 
     this.Refresh(); 
     System.Threading.Thread.Sleep(20); 
    } 

    // Here you KNOW that the picture box is at y-position 20, so there's not need 
    // for the IF 
    pictureBox1.Visible = false; 
    pictureBox2.Visible = true; 
} 

위 코드의 문제점은 UI를 차단한다는 것입니다.

private void AnimationStep(object source, ElapsedEventArgs e) 
{ 
    // The following code needs to be executed in the context of the UI thread. 
    // We need to use this.Invoke in Forms or this.Dispatcher.Invoke in WPF 
    this.Invoke((Action)delegate() 
    { 
     // Move picture. Note that we don't need to update the display here 
     // because the UI thread gets time to do its work while the timer waits 
     // to fire below 
     if (pictureBox1.Top > 20) 
      pictureBox1.Top--; 

     // Show other picture maybe. I use <= here because initially, the 
     // position of the picture box may already smaller than 20. 
     if (pictureBox1.Top <= 20) 
     { 
      pictureBox1.Visible = false; 
      pictureBox2.Visible = true; 
     } 

     // Or let the timer fire again if we still need to animate 
     else 
     { 
      (source as System.Timers.Timer).Start(); 
     } 
    } 
} 

이 같이 작동 다음과 같습니다 :

private void button1_Click(object sender, EventArgs e) 
{  
    // Create a threaded timer 
    System.Timers.Timer animationTimer = new System.Timers.Timer(); 
    animationTimer.Interval = 20; 
    animationTimer.AutoReset = false; // Only one Ping! We'll activate it if necessary 
    animationTimer.Elapsed += new ElapsedEventHandler(AnimationStep); 
    animationTimer.Start(); 

    // Disable the button also, because we don't want another timer instance to 
    // interfere with our running animation 
    button1.Enabled = false; 
} 

을 다음 타이머 화재가 때 호출하는 이벤트를 생성 : 타이머가 만들어집니다 다음과 같이 반응을 유지하기 위해, 나는 타이머를 사용하십시오 20ms 후 한 번 발사. 그런 다음 그림을 한 픽셀 위로 이동 한 다음 애니메이션이 끝나면 다른 그림을 표시하거나 다른 픽셀 위로 그림을 이동하기 위해 타이머를 다시 시작합니다.

이렇게하면 UI가 반응을 유지하면서도 그림을 애니메이션으로 만들 수 있습니다. 단점은 윈도우가 움직이거나 다른 "작업"이 UI 스레드에 의해 수행되어야 할 경우를 대비하여 애니메이션이 부드럽 지 않을 수도 있다는 것입니다.

+0

downvoter가 아니라 OP 코드를 사용해 보았습니다. Sleep 문을 사용하면 UI의 응답 속도가 느려지지만 절전 모드가 완료되면 즉시 그림이 업데이트됩니다. – jac

+0

얼마나 자주 ... ** Downvoter, 댓글을달라고하니? ** –

+0

@jac이 전체 루프는 UI **가 응답하지 못하게 **합니다. 그것은 어쨌든 어떻게 할 것인가가 아니라 그의 코드입니다. –

0

:

this.Invalidate(); 
this.Refresh(); 

을 가정은 윈폼으로 노력하고 있습니다.

1

처음에 b이 20보다 큰 경우 어떻게해야합니까? 루프의 조건이 i < 20이므로 루프가 실행되지 않습니다. 루프가 실행되지 않았으므로 아무 것도 일어나지 않습니다.

루프의 조건을 변경하는 것이 좋습니다. Top- 속성을 줄이면 그림이 위로 올라가는 것이 좋습니다. 처음에 pictureBox1의 Top이 40이라고 가정 해 봅시다.최고 지금보다 20 때문에, 경우 문을 생략 할 수

while(pictureBox1.Top >= 20) 
{ 
    pictureBox1.Top--; 
    System.Threading.Thread.Sleep(20); 
    Invalidate(); 
    Refresh(); 
} 

그리고 당신은 호출 할 수 있습니다 : 다음 코드는 작동

pictureBox1.Visible = false; 
pictureBox2.Visible = true; 

전체 코드 :

while(pictureBox1.Top >= 20) 
{ 
    pictureBox1.Top--; 
    System.Threading.Thread.Sleep(20); 
    Invalidate(); 
    Refresh(); 
} 

pictureBox1.Visible = false; 
pictureBox2.Visible = true;