简体   繁体   中英

C# and windows forms: How to cycle through image files in a directory?

The goal is to make a simple picture viwer. It should read all the images filenames in a specified directory into an array. When I click next button it should show me a file with a filename "array index+1" relative to the current one and so with prev button assuming decrement of index. When I reach the end of the array (last index plus one) with next , index of a current image should be set to zero, and when I reach zero minus 1 index with prev button? the index should be set like "array.length-1" (last index of the array). You know, like cycle-wrapping, looping, or I am not sure how to call it properly. I've managed to make it to work but with one issue: I can't get rid of double zero and double last index when press next and prev accordingly, hard to explain in in words, so here's the code I wrote (I guess I'll skip all the unrelated methods):

// boolean prev and next are set to avoid misplacing of array index


    private void nextImageButton_Click(object sender, EventArgs e)
    {
        if (prev)
        {
            counter = counter + 2;
        }
        if (counter <= filesInDir - 1)
        {
            showImage(currentDirFiles[counter], counter);
            counter++;
        }
        else
        {
            counter = 0;
            showImage(currentDirFiles[counter], counter);

        }
        next = true;
        prev = false;

    }

    private void previousImageButton_Click(object sender, EventArgs e)
    {
       if (next)
        {
            counter = counter - 2;
        }
       if (counter >= 0)
        {
            showImage(currentDirFiles[counter], counter);
            counter = counter -1;
        }
        else
        {
            counter = filesInDir - 1;
            showImage(currentDirFiles[counter], counter);
        }
        prev = true;
        next = false;
    }

as you can see, when I press next and my array index counter becomes bigger than the last actual index of the array, I have to set the index to zero, but at the same time I still have to show the "next" picture (in this case it would be the actual first one, with zero index). But when if this method is called again, it will check (in the second condition) the value of counter -- it will be zero -- and it will show the same picture again! (with zero index) and will be the second time in a row when we see this particular zero-index picture.

I hope I've managed to explain my issue. It was difficult ;)

One way to solve this is increment or decrement the value before showing the picture, so you can then do some boundary checking on the value before trying to access an item from that index in the array.

Before incrementing the value, check to see if it's already at currentDirFiles.Length - 1 . If it is, then set it to 0 ; otherwise do the increment.

Similarly, when decrementing the value, check to see if it's already at 0 . If it is, then set it to currentDirFiles.Length - 1 ; otherwise do the increment.

For example:

private void nextImageButton_Click(object sender, EventArgs e)
{
    counter = counter == currentDirFiles.Length - 1 ? 0 : counter + 1;
    showImage(currentDirFiles[counter], counter);
}

private void previousImageButton_Click(object sender, EventArgs e)
{
    counter = counter == 0 ? currentDirFiles.Length - 1 : counter - 1;
    showImage(currentDirFiles[counter], counter);
}

Another approach would be to create a generic method that will take in a potential value, along with a min and max value for a range, and return a value that is within the range. And to make it more array-friendly (where min value is always 0 and max value is always Length - 1 ), I added an overload that takes an exclusive max value (which would be array.Length):

/// <summary>
/// Enforces that a specified value is within the specified bounds.
/// </summary>
/// <param name="value">The value to check</param>
/// <param name="minValue">The lowest valid value in the range</param>
/// <param name="maxValue">The highest valid value in the range</param>
/// <returns>
/// A value within the specified range based on the initial value. The returned
/// value will wrap around the range in whichever direction it is furthest
/// away from. For example, for a number that is 3 less than minValue, 
/// a number that is 2 less than maxValue will be returned.
/// </returns>
private static int WrapWithinBounds(int value, int minValue, int maxValue)
{
    return value < minValue
        ? maxValue - (minValue - value) + 1
        : value > maxValue
            ? minValue + (value - maxValue) - 1
            : value;
}

private static int WrapWithinBounds(int value, int exclusiveMaxValue)
{
    return WrapWithinBounds(value, 0, exclusiveMaxValue - 1);
}

To use this, our methods would then look like:

private void nextImageButton_Click(object sender, EventArgs e)
{
    counter = WrapWithinBounds(++counter, currentDirFiles.Length);
    showImage(currentDirFiles[counter], counter);
}

private void previousImageButton_Click(object sender, EventArgs e)
{
    counter = WrapWithinBounds(--counter, currentDirFiles.Length);
    showImage(currentDirFiles[counter], counter);
}

I think the issue might be that you were doing show image before updating your counter. Try this:

private void nextImageButton_Click(object sender, EventArgs e)
{
    if (counter <= filesInDir - 1)
    {
        counter++;
        showImage(currentDirFiles[counter], counter);            
    }
    else
    {
        counter = 0;
        showImage(currentDirFiles[counter], counter);
    }
}

private void previousImageButton_Click(object sender, EventArgs e)
{
    if (counter != 0)
    {
        counter--;
        showImage(currentDirFiles[counter], counter);            
    }
    else
    {
        counter = filesInDir - 1;
        showImage(currentDirFiles[counter], counter);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM