Java桌面技術

          Java Desktop Technology

          常用鏈接

          統計

          友情連接

          最新評論

          《FilthyRichClients》讀書筆記(二)-讓Swing正確顯示Gif

          利用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(電玩) 閱讀(42597) 評論(7)  編輯  收藏 所屬分類: NetBeans

          評論

          # re: 《FilthyRichClients》讀書筆記(二)-讓Swing正確顯示Gif[未登錄] 2008-12-12 14:00 Matthew Chen

          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);
          }
          }
            回復  更多評論   

          # re: 《FilthyRichClients》讀書筆記(二)-讓Swing正確顯示Gif[未登錄] 2008-12-12 14:14 Matthew Chen

          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);

          }

          }
            回復  更多評論   

          # re: 《FilthyRichClients》讀書筆記(二)-讓Swing正確顯示Gif 2008-12-12 23:46 sun_java_studio@yahoo.com.cn(電玩)

          @Matthew Chen
          用loading.gif試過嗎?
          記住我提到的“但是事實情況卻是:不要企圖通過這樣簡單的處理達到理想的效果。”  回復  更多評論   

          # re: 《FilthyRichClients》讀書筆記(二)-讓Swing正確顯示Gif[未登錄] 2008-12-13 14:55 Matthew Chen

          試了一下,還真的不行...
          我之前只是用某個的gif動畫  回復  更多評論   

          # re: 《FilthyRichClients》讀書筆記(二)-讓Swing正確顯示Gif 2008-12-16 12:46 電玩

          @Matthew Chen
          用GifAnalysis可以查看gif各frame的delayTime屬性,美工應該知道如何更改這個值。  回復  更多評論   

          # re: 《FilthyRichClients》讀書筆記(二)-讓Swing正確顯示Gif[未登錄] 2009-01-04 12:52 AllenME

          希望繼續發關于這本書的筆記。 看您的blog ,就不用看書了,哈哈  回復  更多評論   

          # re: 《FilthyRichClients》讀書筆記(二)-讓Swing正確顯示Gif[未登錄] 2014-10-16 19:28 1

          很好  回復  更多評論   

          TWaver中文社區
          主站蜘蛛池模板: 山东省| 光山县| 明溪县| 如皋市| 库伦旗| 平泉县| 宁乡县| 紫阳县| 翁源县| 汽车| 安阳市| 象州县| 大英县| 墨竹工卡县| 焦作市| 绵竹市| 南川市| 普安县| 安化县| 达日县| 南京市| 建德市| 图们市| 西乌珠穆沁旗| 镇坪县| 清涧县| 靖安县| 呼伦贝尔市| 花莲市| 贵州省| 建宁县| 凌源市| 阳朔县| 浦东新区| 绿春县| 涞源县| 扬中市| 驻马店市| 仁布县| 读书| 四子王旗|