首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >同步摆动定时器与gif图像

同步摆动定时器与gif图像
EN

Stack Overflow用户
提问于 2015-12-07 17:23:43
回答 1查看 898关注 0票数 0

我有一个gif图像显示在一个无休止的循环中的JPanel上。现在我需要停止动画后,随机数量的帧。事实上,我生成的随机数可以是0或1,假设gif由6个帧组成。如果数字是0,我想停止在第3帧,如果它是1,动画应该冻结在第6帧。

为了实现这一点,我尝试使用一个Swing计时器,它精确地在下一个帧出现时触发事件。因此,如果帧延迟为50 ms,我将构造如下

代码语言:javascript
复制
new Timer(50, this);

可悲的是,这似乎不起作用,事实上动画似乎比计时器慢。(我认为这与装载时间有关。)无论如何,我添加了一些代码来说明问题和(故障)解决方法。

代码语言:javascript
复制
import java.awt.event.*;
import javax.swing.*;

public class GifTest extends JPanel implements ActionListener{

ImageIcon gif = new ImageIcon(GifTest.class.getResource("testgif.gif"));
JLabel label = new JLabel(gif);
Timer timer = new Timer(50, this);
int ctr;

public GifTest() {
    add(label);
    timer.setInitialDelay(0);
    timer.start();
}

@Override
public void actionPerformed(ActionEvent e) {
    ctr++;
    if (ctr == 13){
        timer.stop();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException i) {
        }
    }
}

public static void main(String[] args) {
    JFrame frame = new JFrame("Gif Test");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(new GifTest());
    frame.setSize(150,150);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}
}

对于giftest.gif,它是一个简单的6层,上面有数字1到6,延迟50 is保存。

如果能提供任何帮助,我将不胜感激。

Ps:如果发现没有优雅的方法可以做到这一点,那么检索当前显示的框架也就足够了。那样的话,我可以要求它,当它是第三次停下来。(6)框架。但是,由于任务的上下文,我更倾向于我的解决方案的修改版本。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-12-07 20:02:33

您可以像上面提到的那样解压缩并存储在一个图像数组中(简单明了)。

您还可以使用更高级的选项,使用ImageObserver接口

ImageObserver通过一个特殊的API为加载过程提供监视,名为:

imageUpdate(图像img,int信息标志,int x,int y,int宽度,int高度)

您可以跟踪此API的进度,如下所示:

代码语言:javascript
复制
ImageIcon gif = new ImageIcon();
JLabel label = new JLabel(gif);
ImageObserver myObserver = new ImageObserver() {
      public boolean imageUpdate(Image image, int flags, int x, int y, int width, int height) {
        if ((flags & HEIGHT) != 0)
          System.out.println("Image height = " + height);
        if ((flags & WIDTH) != 0)
          System.out.println("Image width = " + width);
        if ((flags & FRAMEBITS) != 0)
          System.out.println("Another frame finished.");
        if ((flags & SOMEBITS) != 0)
          System.out.println("Image section :" + new Rectangle(x, y, width, height));
        if ((flags & ALLBITS) != 0)
          System.out.println("Image finished!");
        if ((flags & ABORT) != 0)
          System.out.println("Image load aborted...");
        label.repaint();
        return true;
      }
    };
gif.setImageObserver( myObserver );
gif.setImage(GifTest.class.getResource("testgif.gif"));

可以使用return false;停止加载过程。

更新:(使用ImageReader)

使用ImageObserver并不那么直观。

每次需要重新绘制时,它都会更新,并触发完整的动画序列。

虽然您可以将其作为某个点停止,但每次都会从第一个映像执行。

另一个解决方案是使用ImageReader

ImageReader可以将GIF解压缩为一个BufferedImages序列。

然后,您可以根据需要使用计时器控制整个序列。

代码语言:javascript
复制
    String gifFilename = "testgif.gif";
    URL url = getClass().getResource(gifFilename);
    ImageInputStream iis = new FileImageInputStream(new File(url.toURI()));
    ImageReader reader = ImageIO.getImageReadersByFormatName("GIF").next();
    // (reader is actually a GIFImageReader plugin)
    reader.setInput(iis);
    int total = reader.getNumImages(true);
    System.out.println("Total images: "+total);
    BufferedImage[] imgs = new BufferedImage[total];

    for (int i = 0; i < total; i++) {
        imgs[i] = reader.read(i);
        Icon icon = new ImageIcon(imgs[i]);
        // JLabel l = new JLabel(icon));
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34139505

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档