Shuffle random picture from resources on button cl

2019-05-10 03:21发布

问题:

I have 1 picture box, named studPic. What I want to get is, when I click "shuffle" button, to get random image from resources.

private void button2_Click(object sender, EventArgs e)
        {
...     
        }

After research I've found following

http://social.msdn.microsoft.com/Forums/en-US/Vsexpressvcs/thread/38d36fa4-1f5f-43e9-80f6-3c9a4edc7705/

I'm newbie to C#.. Is there easier way to achieve this result? For example, without adding picture names?

UPDATE

List<string> pictureNames = new List<string>();
pictureNames.Add("1");
pictureNames.Add("2");
pictureNames.Add("3");
int randomPictureIndex = new Random().Next(0, pictureNames.Count);
string randomPictureName = pictureNames[randomPictureIndex];
pictureNames.Remove(randomPictureName);
Image img = Properties.Resources.randomPictureName; //erroor
studPic.Image = img;

getting error message Error 1 'Properties.Resources' does not contain a definition for 'randomPictureName'

回答1:

I wouldn't use System Resources for this. They're not as maintainable as the file system for disconnected software.

Have your images in a folder for your app. This way they can be updated/changed easily. Say :

C:\Ninjas - app
c:\Ninjas\images - images

Create an array that holds these images.

string[] files = System.IO.Directory.GetFiles("c:\ninjas\images");

You'll need to put some filters on the GetFiles to ensure you only get pictures.

Now grab a random position in that array (you've already shown you know how to do random numbers).

We have the array, let's shuffle it and then you can go through them sequentially (way faster than randomly picking on. CPU will love you for it)

    private string[] files;
    private int currentIndex = 0;

    private void initializeImages()
    {
        //Grab directories in your images directory
        string appRoot = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
        files = System.IO.Directory.GetFiles(appRoot + @"\images");
        Random rnd = new Random();
        files = files.OrderBy(x => rnd.Next()).ToArray();
    }


    private void setImage()
    {
        pictureBox1.ImageLocation = files[currentIndex];
    }

    private void previousImage()
    {
        currentIndex = currentIndex > 0 ? currentIndex - 1 : 0;
        setImage();
    }

    private void nextImage()
    {
        currentIndex = currentIndex < files.Length - 1 ? currentIndex + 1 : files.Length - 1;
        setImage();
    }

A couple things:

  • Don't hard code the file path. Have this in your app.config file, and reference it.
  • You can put the file array global so it doesn't need to be ran each time.

If you want to have this as a slide show that runs until the user cancels it I'd recommend the following:

  • Use a timer object that calls a method to increase the image count, which changes the picture.
  • Don't use a thread.sleep on your GUI as it will pause your GUI - not a nice thing.

If you want to add Next/Previous buttons, you'll need to have a global index (say currentIndex) that can be increased/decreased, then call code to set the image



回答2:

Some setup is involved on your part, but the naysayers are mostly right. This is not a very valid solution for a production application. That being said, I doubt this is something you're distributing to tons of people, so we'll call this an academic exercise. If you were to simply add a resource to your application and name it "ImageResource" (any name will do), and add your images to it, you can then use the following code (assuming the corresponding UI elements exist).

First, we create a function to extract Bitmaps from your resource.

private Bitmap[] GetResourceImages()
{
    PropertyInfo[] props = typeof(ImageResource).GetProperties(BindingFlags.NonPublic | BindingFlags.Static);
    var images = props.Where(prop => prop.PropertyType == typeof(Bitmap)).Select(prop => prop.GetValue(null, null) as Bitmap).ToArray();

    return images;
}

Second, we create a function that will randomize an image based on the available images:

private void RandomizePicture()
{
    Bitmap[] images = GetResourceImages();
    if (images == null || images.Length == 0)
    {
        //Nothing to do here...
        return;
    }

    int maxValue = images.Length;
    Random r = new Random();
    int idx = r.Next(maxValue);
    this.uxStupidPic.Image = images[idx];
}

Finally, call that function on a button click:

private void btnRandmoize_Click(object sender, EventArgs e)
{
    this.RandomizePicture();
}

And voila, randomized images from a resource files. Happy coding!

EDIT: Just noticed you said you were using an Application resource rather than a random resource file. Simply replace "ImageResource" with "Properties.Resources", in GetResourceImages, and you'll be in business.



回答3:

I like Ryan Ternier's answer very simple and elegant, I was going to post a solution similar to his.

I just want to comment on the reasons why line doesn't/shouldn't work:

Image img = Properties.Resources.randomPictureName;

  1. Is because the Properties Resources is looking for a resource called "randomPictureName" rather than the actual name itself.
  2. The way the Properties.Resources object works is that it looks for all your resources in your solution's properties at runtime, after code compilation. It wouldn't work the way you want it to since you're trying to pass in a static variable that may not even exist in resources, forcing you to wrap your method around a try/catch statement just in case.

http://msdn.microsoft.com/en-us/library/7k989cfy(v=vs.80).aspx