0

Can't figure out why image in label1 connected with imageList1 doesn't want to change more than once after pressing of a mouse button. Imagelist consists of 7 images which I want to have gradually appear in label element...that was the whole idea.

private void button1_Click(object sender, EventArgs e)
{
    int number = 0;
    for (int i = 0; i < imageList1.Images.Count; i++)
    {
        label1.Image = imageList1.Images[number++];             
    }            
}

The default ImageIndex in label1 properties is set to 0 (first image) and after the for loop it gets to index1.

Tomas Gryzbon
  • 97
  • 3
  • 13
  • 2
    Your code does not do what you say it does in your description. It always sets the label image to the last image in the image list. – MicroVirus Jun 19 '14 at 11:58
  • I don't think that the images will appear gradually just with this code. And what UI do you use? WinForms? And your label is PictureBox? – Eugene Podskal Jun 19 '14 at 11:59
  • try putting it as imageList1.Images[i] , i think the increment of number ++ might be problem – lloydom Jun 19 '14 at 12:00

4 Answers4

1

Your form will only repaint once the whole button event ran. That means you will only ever see the last image. Look into background workers or maybe timers to have animation. Maybe WPF is the way to go if animation is the main purpose of your program.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
1

I am guessing that the last image stays? If you want the images to appear one by one with a timeout you should do something like

private async void button1_Click(object sender, EventArgs e)
{
    foreach (Image image in imageList1)
    {
        await Task.Delay(1000); //wait for one second before changing
        label1.Image = image;
    }            
}

Of course depending on your requirements you may want to disable the button and as pointed out by @nvoigt you may want to use some animation capabilities of the UI framework.

Stilgar
  • 22,354
  • 14
  • 64
  • 101
1

Your loop does assign the images OK but there is no time to show them because updating the UI is not happening before the loop is through.

You could force the UI update by inserting an Application.DoEvents()

label1.Image = imageList1.Images[number++];   
Application.DoEvents();

You can try it but you should not actually use this as your solution! It has two serious issues, none of which you want:

  • It gives you no control over the animation speed.
  • Application.DoEvents can introduce serious problems in your code and you should not get into the habit of using it at all. Look it up or just believe it!

The best way to do any animation in Winforms is to use a Timer. In the Button click you set it up and start it. In its Tick you do the animation..

Have alook at this post for a button animation example! Instead of Mouse_Enter use your button click. Stop the Timer when the images have all been shown!

If all you want to do is playing around a little getting used to Timers is highly recommended and there is no need at all for WPF. If you will need a lot of high class animation WPF is indeed the way to go.

Here is the code to a minimal solution:

Timer timer1 = new Timer();
int imageIndex = 0;

private void timer1_Tick(object sender, EventArgs e)
{
    if (imageIndex >= imageList1.Images.Count ) timer1.Stop(); 
    label1.Image = imageList1.Images[imageIndex++]; 
}


private void button1_Click(object sender, EventArgs e)
{
   imageIndex = 0;
   timer1.Interval = 100; // change ms to suit your needs!
   timer1.Start();              
}
Community
  • 1
  • 1
TaW
  • 53,122
  • 8
  • 69
  • 111
0

There are various issues with your code.

  • By incrementing number inside the loop, you force it to have the same value as i. If that's what you want to do, why not simply use i?
  • You never let the UI thread update the display. The UI thread will update the display only after the event handler finishes.

The result is that only the last image will be displayed.

To allow the UI thread to update the display, you need to use Application.DoEvents, eg:

foreach(Image image in imageList1.Images)
{
    label1.Image = image;
    Application.DoEvents();
}

Of course this will just go through all the images at once, so you'll just see a blur.

If you want a simple, smooth animation, use an [animated GIF2 or use WPF. Trying to do this in Windows Forms with individual images is not straightforward.

If you want to show an animation, you can put a delay as @Stilgar suggests, although this won't guarantee a smooth animation. Thread switching or high CPU load means that the delay between images will always be greater than the delay amount. The result will be a jerky animation.

You can use a timer event to update the image. This is better, but high CPU load can still delay processing of the event. Only WPF can guarantee the animation will be smooth without complex coding.

Community
  • 1
  • 1
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236