如何在 GIF 结束后更改图片框

本文关键字:GIF 结束 | 更新日期: 2023-09-27 18:35:34

我有一个PictueBox,我有一些骰子,我想播放一个"掷骰子"的动画,我用骰子做了一个.gif,但是在骰子停止滚动后,我想要我得到的实际骰子编号,我有一个随机的功能来处理它。

我的问题是,我按下"掷骰子"按钮,它会播放动画,动画结束后,我应该在图片框中设置实际出现的骰子。 但它立即点击实际来的骰子数字,跳过动画;

这是它的工作原理:

dice1.Image = Resources.DiceAnimation; //Here the gif is called to be played
int x = rollDice(); //Here I roll the dice
switch (x){
     case 1: dice.Image = resources.diceFace1; //Image set depending on x
             break
     case 2: //etc...
}

如何在 GIF 结束后更改图片框

可能需要

做两件事。

首先,您可能需要确保您的PictureBox收到 gif 图像并且它知道它。为此,请检查此答案和此答案。这些帖子有代码可以逐帧显示GifImage

public class GifImage
{
    private Image gifImage;
    private FrameDimension dimension;
    private int frameCount;
    private int currentFrame = -1;
    private bool reverse;
    private int step = 1;
    public GifImage(string path)
    {
        gifImage = Image.FromFile(path);
        //initialize
        dimension = new FrameDimension(gifImage.FrameDimensionsList[0]);
        //gets the GUID
        //total frames in the animation
        frameCount = gifImage.GetFrameCount(dimension);
    }
    public bool ReverseAtEnd {
        //whether the gif should play backwards when it reaches the end
        get { return reverse; }
        set { reverse = value; }
    }
    public Image GetNextFrame()
    {
        currentFrame += step;
        //if the animation reaches a boundary...
        if (currentFrame >= frameCount || currentFrame < 1) {
            if (reverse) {
                step *= -1;
                //...reverse the count
                //apply it
                currentFrame += step;
            }
            else {
                currentFrame = 0;
                //...or start over
            }
        }
        return GetFrame(currentFrame);
    }
    public Image GetFrame(int index)
    {
        gifImage.SelectActiveFrame(dimension, index);
        //find the frame
        return (Image)gifImage.Clone();
        //return a copy of it
    }
}

像这样使用它(请注意,您需要一个Timer对象):

private GifImage gifImage = null;
private string filePath = @"C:'Users'Jeremy'Desktop'ExampleAnimation.gif";
public Form1()
{
    InitializeComponent();
    //a) Normal way
    //pictureBox1.Image = Image.FromFile(filePath);
    //b) We control the animation
    gifImage = new GifImage(filePath);
    gifImage.ReverseAtEnd = false; //dont reverse at end
}
private void button1_Click(object sender, EventArgs e)
{
    //Start the time/animation
    timer1.Enabled = true;
}
//The event that is animating the Frames
private void timer1_Tick(object sender, EventArgs e)
{
    pictureBox1.Image = gifImage.GetNextFrame();
}

其次,要知道您要运行GIF图像多长时间,您可能需要像这样获取GIF图像的帧持续时间:

double delayIn10Ms; //declare somewhere
//Initialize on your form load
PropertyItem item = img.GetPropertyItem (0x5100); // FrameDelay in libgdiplus
// Time is in 1/100th of a second
delayIn10Ms = (item.Value [0] + item.Value [1] * 256) * 10;

然后利用delayIn10Ms时间加上可能更多的时间来停止计时器。您可能还想检查计时器上次滴答的时间并存储它。如果它超过了给定的延迟时间,那么您应该停止计时器并在掷骰子时再次启动它,在您的switch情况下进行图像分配。

DateTime currentTick = DateTime.Min;
DateTime startTick = DateTime.Min;
private void timer1_Tick(object sender, EventArgs e)
{
    currentTick = DateTime.Now;
    if ((currentTick - startTick).TotalSeconds / 100 < delayIn10Ms)
        pictureBox1.Image = gifImage.GetNextFrame();
    else
        timer1.Stop(); //stop the timer        
}
//And somewhere else you have
timer1.Start(); //to start the timer
int x = rollDice(); //Here I roll the dice
switch (x){
     case 1: dice.Image = resources.diceFace1; //Image set depending on x
             break
     case 2: //etc...
}

您可以使用将 Interval 属性设置为动画长度的计时器,并将其 Tag 设置为 0,然后在计时器中编写代码:

if(timer.Tag == "0")
    timer.Tag == "1";
else if(timer.Tag == "1")
{
    int x = rollDice();
    switch (x)
    {
        case 1: dice.Image = resources.diceFace1; break;
        case 2: //etc...
    }
    timer.Tag == "0";
    timer.Stop();
}