Java Desktop Technology
利用gif图片制作简单动画是常用的渲染手段,swing虽然支持gif图片格式并可以自动地实现动画效果。 通常最简单地将gif图片放到swing组件上是调用JButton或JLabel的setIcon(Icon icon)方法。 还有一种方法是重写paintComponent(Graphics g)或paint(Graphics g)方法。例如 public class ShowGifPanel extends JPanel{ ImageIcon image = new ImageIcon("/root/opt/loading.gif");
@Override public void paint(Graphics g) { g.drawImage(image.getImage(), 0, 0, this); } } 通过上述方法呈现如下3个gif。 但是事实情况却是:不要企图通过这样简单的处理达到理想的效果。如果你这样做的话马上会发现gif的刷新率往往非常快,看上去gif图片桢刷新很快,或者应该说太快了。 swing还提供了一种实现手段是设置一组相似的gif,通过轮循显示来呈现,通过下图就明了了。 这样虽然可以呈现,但是对于一个动画来说就必须提供多个gif。对于占用空间和给美工的负担都不利。 如果你使用SWT呈现Gif,Eclipse提供了一个方案。 http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet141.java?view=co 其基本原理就是将Gif的各个桢轮循地显示,如果你以这个程序运行loading.gif,看上去还是很快,可以通过修改第131~137行之间的代码来调节刷新率。这样SWT就能完美实现处理Gif了。 不幸的是,将SWT的那种方式移植到Swing中却达不到很好的效果。在Swing中要想完美实现处理Gif需要额外的一些工作。
首先需要对Gif这种图片格式有一些基本认识。 第一:Gif由一系列Image组成,也就是桢,Gif动画就是连续地显示这些桢,但是这还不够。 第二:无论某一时刻轮循到哪一桢,第1桢,总是要当作背景画出来,而且第1桢也是所有桢当中最长最高的,它的尺寸也是整个Gif图象的尺寸,位置从(0, 0)开始,其余各桢可能只是描述与相临各桢变化的部分,所以长和高要小且不完整,起始位置是该桢相对整体背景的位置。(这点SWT也是这样做的) 第三:Gif动画连续显示不一定是各个桢轮循单独显示,而是不仅仅显示当前该显示的桢,还要向前追溯到"第一桢",从"第一桢"开始到当前应该显示的桢组成的连续一系列"桢簇",所以某一时刻单单显示背景和当前桢是不够的,而是显示背景和当前"桢簇"。""桢簇""是我自己取的名字,而且我看SWT轮循的例子中并没有用到"桢簇",而是传统的单桢轮循。但是同样的方法对Swing不奏效,现在我对此还不得其解。关于"第一桢",是和com.sun.imageio.plugins.gif.GIFImageMetadata类的disposalMethod属性有关,在SWT中这个属性是org.eclipse.swt.graphics.ImageData.disposalMethod。disposalMethod据我的研究是描述处理桢的方法,常见的disposalMethod取值有none(取值0,不处理)、Background(取值2,背景)两种,所谓的当前桢的"第一桢"就是向前追溯到最近的disposalMethod取值为2的那一桢的下一桢,也就是说或者"第一桢"的前一桢的disposalMethod取值为2,或者"第一桢"就是Gif索引为2的桢,因为Gif的第1桢总要当背景显示。 第四:桢的元数据在SWT中用org.eclipse.swt.graphics.ImageData类封装,在Swing中对应的是com.sun.imageio.plugins.gif.GIFImageMetadata(可是截止到JDK6.0 u11,这个类的版本号还是0.5,有些另人失望:(),可以通过次类获取到delayTime这个属性,也就是下一桢的间隔时间,但是有很多Gif,这个值总是0,所以Swing显示频率相当的快。
以下是本人写的2个参考实现,其中GifAnalysis.java是gif的分析工具,它将Gif的各个桢单独拿出来分析比对,并列出了上面提到的一些属性。如下图 通过比较发现loading.gif各个桢的delayTime均为0,因此单纯地将loading.gif设置为JLabel等组件的icon属性效果必定会出问题,可以通过美工解决。 Gif.java是呈现gif的参考,需要留意构造函数public Gif(File gifFile, int delayFactor),第二个参数是延时因子,数值越大每一桢的间隔就越长,对于loading.gif该值调节为105较为合适,而tt1.gif和javafx-loading-100x100.gif这个值应该是10。 参考代码这里下载
posted on 2008-12-07 20:36 sun_java_studio@yahoo.com.cn(电玩) 阅读(42581) 评论(7) 编辑 收藏 所属分类: NetBeans
swing 也可以很简单地实现gif动画绘制,同时试了一下JLabel和JButton,直接setIcon就可以了。 public class ShowGifPanel extends JPanel{ ImageIcon image = new ImageIcon("/root/opt/loading.gif"); protected void paintComponent(Graphics g) { //记得调用超类方法,还有容器的绘制应该在这个方法里添加才对。 super.paintComponent(g); g.drawImage(image.getImage(), 0, 0, this); } } 回复 更多评论
import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.Graphics; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import com.matthew.common.UIManagerUtil; public class GifDraw { private JFrame frame; /** * Launch the application * * @param args */ public static void main(String args[]) { try { UIManagerUtil.setSystemLookAndFeel(); GifDraw window = new GifDraw(); window.frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } /** * Create the application */ public GifDraw() { initialize(); } /** * Initialize the contents of the frame */ private void initialize() { frame = new JFrame(); frame.setBounds(100, 100, 500, 375); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); final ImageIcon i = new ImageIcon("105.gif"); final JPanel panel = new JPanel() { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(i.getImage(), 0, 0, this); } }; panel.setLayout(null); frame.getContentPane().add(panel, BorderLayout.CENTER); final JPanel panel_1 = new JPanel(); panel_1.setLayout(new FlowLayout()); frame.getContentPane().add(panel_1, BorderLayout.NORTH); final JLabel label = new JLabel(i); label.setText("New JLabel"); panel_1.add(label); final JButton button = new JButton(i); button.setText("New JButton"); panel_1.add(button); } } 回复 更多评论
@Matthew Chen 用loading.gif试过吗? 记住我提到的“但是事实情况却是:不要企图通过这样简单的处理达到理想的效果。” 回复 更多评论
试了一下,还真的不行... 我之前只是用某个的gif动画 回复 更多评论
@Matthew Chen 用GifAnalysis可以查看gif各frame的delayTime属性,美工应该知道如何更改这个值。 回复 更多评论
希望继续发关于这本书的笔记。 看您的blog ,就不用看书了,哈哈 回复 更多评论
很好 回复 更多评论
Powered by: BlogJava Copyright © sun_java_studio@yahoo.com.cn(电玩)