AWT和Swing顯示GIF 動(dòng)畫
很早就知道AWT和Swing組件可以直接通過 Graphics.drawImage() 來顯示 GIF 動(dòng)畫, 但是一直不太做界面程序, 也就沒有仔細(xì)用過.
現(xiàn)在做 WoW Traverser, 因?yàn)樾薷氖钱惒教峤坏椒?wù)器, 所以有必要對(duì)正在提交的更改進(jìn)行界面提示, 打算做個(gè)黃色alpha混和的漸變閃動(dòng)效果來實(shí)現(xiàn), 于是第一反應(yīng)是做一個(gè)透明度不斷變化的純黃色GIF, 畫到界面上去.
但是用GIMP總是做出來效果不對(duì), 于是想干脆自己寫程序?qū)崿F(xiàn), 反正就是加個(gè)黃色的混和, 利用AWT和Swing顯示GIF相同的機(jī)制, 效率和穩(wěn)定性應(yīng)該也不會(huì)差. 最后花了一天時(shí)間研究AWT和Swing的動(dòng)畫機(jī)制.
雖然也了解了一些原本不知道的細(xì)節(jié), 但是結(jié)果還是讓我很失望, 原來drawImage時(shí)就是把當(dāng)前Component注冊(cè)為該圖片的ImageObserver, 這樣GIF的下一幀到了需要顯示的時(shí)間時(shí), 通過 imageUpdated() 通知這個(gè)組件, 最終是在 java.awt.Component.imageUpdated() 中處理這個(gè)問題. 令人非常失望的是, Java都到了1.5了, AWT中這個(gè)地方的處理還是那么蹩腳, 它只是檢查了一下更新頻率有沒有超過系統(tǒng)規(guī)定的上限, 只要沒超過, 那么它就對(duì)Component發(fā)一個(gè)完全的repaint()請(qǐng)求, 甚至都沒有去計(jì)算該圖片的覆蓋區(qū)域, 設(shè)置一個(gè)Clip區(qū)域以減少不必要的繪圖操作.
更甚者, 即使之后你不再顯示這個(gè)GIF了, AWT也不會(huì)自動(dòng)從這個(gè)『曾經(jīng)』顯示的圖片的ImageObserver列表中去掉這個(gè)Component, 最終導(dǎo)致的結(jié)果, 就是即使不再顯示那個(gè)GIF, 這個(gè)Component還是會(huì)以那個(gè)GIF的刷新頻率不斷的毫無必要的去repaint() !! 這不但蹩腳, 簡直都有點(diǎn)齷齪.
而且費(fèi)了半天勁, 連手工去取消ImageObserver的接口都沒有找到, 也就是說: 如果不是永久性的顯示一個(gè)GIF, 千萬不要通過java.awt.Toolkit.createImage() 構(gòu)造 GIF 的 java.awt.Image對(duì)象然后往你自己的Component上畫, 否則這個(gè)GIF圖片將長時(shí)間占用內(nèi)存以及 ImageFetcher 線程的CPU資源, 同時(shí)耗費(fèi)CPU時(shí)間和GUI資源用來絲毫沒有必要的反復(fù)repaint你的Component.
【編輯推薦】