2013-12-11 101 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; 
    } 
} 

任何想法如何解決?

+7

哪部分是錯的?現在的行爲與你期望的行爲相比如何? –

+0

它沒有錯誤,它只是不工作。點擊按鈕後沒有任何反應。 – Noterezeck

+0

作爲調試過程的一部分,你是否已經完成了代碼?到目前爲止,這是任何人的猜測。甚至可能是這個事件處理程序根本沒有被解僱。驗證它是否被初學者擊中,然後逐步檢查所有整數的值等。 –

回答

3

這似乎是錯誤的:

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

這將循環而i < 20。但是,從您的代碼中可以看出,如果達到Top == 20,您想顯示另一張圖片。所以我想這應該是i >= 20if應該是Top <= 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; 
} 

上述代碼的問題是它阻止了用戶界面。爲了保持它的響應,我會使用一個計時器如下:

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; 
} 

然後,創建事件計時器的火災時,被稱爲:

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(); 
     } 
    } 
} 

這個工作原理如下:將定時器創建20ms後會發生一次火災。然後將圖片向上移動一個像素,然後在動畫完成時顯示另一個圖片,或者再次啓動計時器以將圖片上移到另一個像素。

這使UI保持響應,並且仍然允許您爲您的照片製作動畫。缺點是,動畫可能不如你想要的那樣流暢,以免你的窗口被移動或者其他「工作」需要由UI線程完成。

+0

不是downvoter,但我嘗試了OP代碼。睡眠語句使得用戶界面響應速度非常緩慢,但只要睡眠完成,圖片就會更新。 – jac

+0

多久...... ** Downvoter,小心評論?? ** –

+0

@jac整個循環使UI **無法響應。這不是我怎麼做,但它是他的代碼。 –

0

pictureBox1.Top分配,通話結束後:

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

假設你正在使用的WinForms工作。

1

如果最初b大於20,該怎麼辦?循環將不會運行,因爲循環中的條件是i < 20。因爲循環沒有運行,所以不會發生任何事情。

考慮改變循環中的條件。您可能希望圖片向上移動,因爲您正在減少Top-屬性。假設最初pictureBox1的頂部是40。下面的代碼將工作:

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

頂起現在低於20,可以省略if語句,你可以直接撥打:

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;