开发者

C# display images randomly and one after another

I am creating a simple form based message display system, each message is a jpeg image, what I want to achieve is when the program loads (just after a user has logged on) one of the jpg's is randomly selected and shown, if the user clicks the Next button another jpg is shown until all have been displayed. I think I need to read each image into an array and then randomly select one from the array and then when a user clicks Next move on to the next item in the array. One caveat is that I don't want the program to lock open the jpg files as others need to be able to delete them.

My current code is below, I would appreciate any help and advice you can offer.

private void Form1_Load开发者_运维百科(object sender, EventArgs e)
 {
      var rand = new Random();
      var files = Directory.GetFiles(@"\\server\screens\", "*.jpg");
      pictureBox1.Image = System.Drawing.Bitmap.FromFile(files[rand.Next(files.Length)]);  
 }

private void buttonNextImage_Click(object sender, EventArgs e)
 {
      var rand = new Random();
      var files = Directory.GetFiles(@"\\server\screens\", "*.jpg");
      pictureBox1.Image = System.Drawing.Bitmap.FromFile(files[rand.Next(files.Length)]);
 }

Many thanks Steven


Don't use Bitmap.FromFile, use Bitmap.FromStream:

using(var fs = new FileStream(files[rand.Next(files.Length),
                              FileMode.Open, FileAccess.Read))
{
    pictureBox1.Image = System.Drawing.Bitmap.FromStream(fs);
}

I don't know how to create an array of images

var files = Directory.GetFiles("\\\\server\\screens\\", "*.jpg");
var images = new Image[files.Length];
for(int i = 0; i < files.Length; ++i)
{
    using(var fs = new FileStream(files[i], FileMode.Open, FileAccess.Read))
    {
        images[i] = System.Drawing.Image.FromStream(fs);
    }
}


Two things here:

  1. Move your random instance out to a class member so that it wil only be instantiated once.
  2. After you display the image, remove it from the files array so that only the images you have not shown remain in the list. When the list is empty, you know you have shown them all.


Expanding on Øyvind Bråthen's answer, you could reset the array once all pictures have been shown, also you could maybe use a timer to, every so often automatically change the image?


I believe that you've 2 options:

a) You load JPG files into memory streams (worst option).

b) You create temp files with the same name and a suffix like "tmp" (i.e. "1.tmp.jpg").

Directly taking "b", after creating the copies, you'd make an index of those files you want to show randomnly in the class level.

After that, using some sort of timer in order to change the image after every tick.

Finally, after every tick, you can synchronize that array of file paths to let your program show the latest and up-to-date ones.

This is my suggestion :)


List of tips:

  • Don't make an array of pictures; make a HashSet<string> of filenames you've already shown. Then, when NEXT is clicked, iterate through the folder again and ignore the filenames you've already shown. From what remains (if any), pick one at random. This way, even if folder contents change in runtime, you'll still get the most of it. And you won't waste memory by loading all images at once.
  • When it's time to display a picture, load it like you do, then Clone() it, and then Dispose() the original. That way it doesn't lock the file.
  • When showing the next image, don't forget to Dispose() the previous one to free up resources.


Here's a general way to go about your request.

  1. Load all the jpeg files in the directory of choice (from your sample, \\Server\Screens\) into an array.

  2. Randomize the file array. Here is a sample implementation of shuffling an array: Most efficient way to randomly shuffle a list of integers

  3. Load the first picture in the array. The array obviously contains the file names so you cannot just point the PictureBox's Image property to the desired element; you'll have to load the image.

    Since you don't want to lock the images, it is recommended to load the images from a stream (refer to @max's answer).

  4. When the user clicks on the next button, load the next picture. You'll have to check if the file exists since from your question, I infer a user might delete a file before it's loaded.


public static int id = 0;
private void timer1_Tick(object sender, EventArgs e)
{
    id = id + 1;
    filelocation = "E:\\example\\" + id + ".bmp";
    pictureBox1.Image = System.Drawing.Bitmap.FromFile(filelocation);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜