效果圖
目前成都創(chuàng)新互聯(lián)公司已為上1000家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)絡(luò)空間、網(wǎng)站改版維護、企業(yè)網(wǎng)站設(shè)計、濉溪網(wǎng)站維護等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
參考代碼
import?java.awt.*;
import?java.awt.event.*;
import?javax.swing.*;
public?class?MoveTextFrame?extends?JFrame?{
JLabel?jl;//文字標簽
int?speed=2;//移動速度
public?MoveTextFrame()?{
jl?=?new?JLabel("文字動畫");
jl.setForeground(Color.RED);
add(jl);
setSize(380,?100);//窗口大小
setLocationRelativeTo(null);//窗口居中
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
//設(shè)置定時器,?每隔25毫秒,改變一次文字標簽的位置
Timer?t?=?new?Timer(25,?new?ActionListener()?{
public?void?actionPerformed(ActionEvent?e)?{
int?x?=?jl.getX()+speed;//計算移動后的位置
if(x=390){//如果超過就指定像素,就重新從左邊開水移動
x=-30;
}
jl.setLocation(x,?jl.getY());//更新位置
//repaint();
}
});
t.start();
}
public?static?void?main(String[]?args)?{
new?MoveTextFrame();
}
}
一: 用多線程播放一組圖片, 實現(xiàn)動畫片的效果; 類似于逐幀動畫,每個圖片是動畫的一幀
二: 在awt/swing界面里, 可以使用paint方法,去繪制圖形,然后用swing提供的Timer或者多線程技術(shù),去刷新繪制的圖形
三:在JavaFX里, 本身就支持動畫,并且封裝了很多動畫效果可以直接使用,比如逐幀動畫.縮放動畫,漸變動畫,旋轉(zhuǎn)動畫,位置動畫等.
強烈推薦使用javaFX來實現(xiàn)動畫, 因為javaFX是現(xiàn)代化的圖形界面工具,具有簡單,強大,組件豐富,跨平臺,支持Html5, 支持表格, 支持動畫等多種優(yōu)勢?
下面是一個javaFX繪制的動態(tài)表格
javaFX動態(tài)表格
在Java D場景中插入動畫片段使 D內(nèi)容更加有趣充實 一段動畫可以在更令人信服的背景下展示 例如飄動的云 繁忙的城市街道 或者是從窗向外看的效果 動畫可以在屏幕效果和游戲效果之間任意轉(zhuǎn)換 這篇文章被分為兩個部分 描寫我怎樣實現(xiàn)一個Java D動畫屏幕效果 在這個部分 我將說明我怎樣利用JMF(Java Media Framework) 特別是在JMF Performance Pack for Windows v e情況下 我的另外兩個工具是J SE 和Java D 我將討論另外的使用Quicktime for Java的動畫屏幕版本 圖 是應(yīng)用JMF Movie D在不同時間截取的兩幅截屏 右邊截屏是從屏幕后看的效果 圖 Movie D應(yīng)用截屏 此應(yīng)用程序中重點 JMF和Java D的集成 屏幕以任意尺寸成倍增加在一個應(yīng)用程序 由于屏幕是Java D的Shape D類的一個子類 因此它可以很容易的統(tǒng)一到各種Java D場景中 程序執(zhí)行使用Model View Controller設(shè)計模式 屏幕是一個視頻元素 由JMFMovieScreen類描述 動畫是一個由JMFSnapper類控制的模型部分 一個Java D Behavior類 TimeBehavior 控制動畫定時定期更新 所有JMF編碼都存放在JMFSnapper類 可以很方便的測試各種變化 這篇文章的第二部分JMFSnapper由QuickTime for Java版本中的QTSnapper取代 Java D 的使用將會使動畫的播放速度毫無困難的上升到 幀/秒 使用JMF出現(xiàn)問題的討論 問題是我首選解決方案將不會工作 JMF有可能變?yōu)橐粋€巨大的API 但在其內(nèi)部仍有一些程序沒有及時運行 我坐在山上 事實上 我正坐在一個冰冷的辦公室 我真正的意思是說這篇文章建立在大量Java D和JMF背景知識之上 我將不會細致地解釋Java D的基礎(chǔ)知識 因為它們都可以在O Reilly文章Killer Game Programming in Java(以下簡稱KGPJ)中找到 例如 圖 場景效果圖是其第 章中的輕微改良Checkers D的版本實例 我再生了這些編碼以生成底版 藍天和燈光 假如你不想買這本書 沒關(guān)系 所有篇章的初稿和所有編碼都可以在此書的站點查閱 在此文章中 我將會解釋我用來從動畫中抽取幀的JMF技術(shù) 我將不會討論流媒體或者編碼轉(zhuǎn)換 應(yīng)用簡述 動畫由JMFSnapper類加載播放 并且不斷的循環(huán)播放直到被停止 JMFMovieScreen生成動畫屏幕 并在底版上控制Java D四邊形 圖 顯示這些類的應(yīng)用(該場景圖說明場景中Java D節(jié)點怎樣連接在一起) 圖 Movie D場景圖 圖 種的很多細節(jié)可以被忽略 此圖KGPJ 章中的得Checkers D實例有很多相似之處 只有特殊動畫的節(jié)點是新的 由于節(jié)點關(guān)系 JMFMovieScreen和TimeBehavior對象以三角形表示 JMFSnapper對象不屬于這張圖 但由JMFMovieScreen調(diào)用 每 毫秒 TimeBehavior對象調(diào)用JMFMovieScreen類中的nextFrame()方法 接下來調(diào)用JMFSnapper中的getFrame()方法獲取動畫中當(dāng)前播放的幀 由JMFMovieScreen控制成像 TimeBehavior是Java D的Behavior類的子類 它是Java D應(yīng)用的計時器 它與KGPJ 章中的 D sprites實例中的TimeBehavior類十分相似 觀察應(yīng)用過程的另一種方式就是察看它的UML類圖表 圖 給出 類中的公共方法被顯示 圖 Movie D類圖表 Movie D的子類JFrame WrapMovie D是JPanel的一個子類 圖 展示了WrapMovie D如何構(gòu)建場景圖 和將其譯成應(yīng)用的JPanel 他使用CheckerFloor 和ColouredTiles類構(gòu)建底版 JMFMovieScreen創(chuàng)建動畫屏幕 將其加入場景中 通過創(chuàng)建一個JMFSnapper對象開始動畫 TimeBehavior每 毫秒調(diào)用JMFMovieScreen中的nextFrame()方法 nextFrame()調(diào)用JMFSnapper中的getFrame()得到當(dāng)前幀 這個例子中的所有編碼 此文章的早期版本可以在KGPJ網(wǎng)點查詢 準備動畫 動畫 它的屏幕和更新屏幕的TimeBehavior對象 都是由WrapMovie D中的addMovieScreen()方法創(chuàng)立 // globalsprivate BranchGroup sceneBG;private JMFMovieScreen ms;// the movie screenprivate TimeBehavior timer;// to update screenprivate void addMovieScreen(String fnm){ // put the movie in fnm onto a movie screen ms = new JMFMovieScreen( new Point f( f ) f fnm);sceneBG addChild(ms);// set up the timer for animating the movie timer = new TimeBehavior( ms);// update movie every ms (== frames/sec) timer setSchedulingBounds(bounds);sceneBG addChild(timer);}兩個Java D addChild()方法調(diào)用JMFMovieScreen和TimeBehavior節(jié)點間的連接 setSchedulingBounds()激活TimeBehavior節(jié)點 創(chuàng)建動畫屏幕 JMFMovieScreen是Java D的Shape D類的一個子類 所以必須仔細說明它的外形的幾何形狀和外觀 幾何形狀是指動畫圖像的四個邊尺寸上成比例 它的最大尺寸(高 寬)必須向構(gòu)造器仔細說明 這個四方形是垂直的 朝向Z軸正方向 可以在底版的任何位置被定位 四方形外觀是雙面 允許從前或后觀看動畫 結(jié)構(gòu)是用雙線性插值 可以降低動畫圖像的像素化 大多數(shù)的功能是從KGPJ 章中的FPS(first person shooter)實例中的ImageCsSeries類拷貝而來 ImageCsSeries在一個區(qū)域中顯示一系列的GIF圖片 為了簡短起見 我僅描述了JMFMovieScreen與ImageCsSeries的不同特征 高效顯示圖像動畫中的一個幀被轉(zhuǎn)換結(jié)構(gòu)擴大四倍 分為兩個步驟 第一步 提供的BufferedImage傳給Java D的ImageComponent D對象 然后傳給Java D Texture D 區(qū)域的圖像更新非???每秒更新 幀 要求結(jié)構(gòu)更新 次 因此結(jié)構(gòu)有效率的更新非常的重要 這種高效率在利用BufferedImage和ImageComponent D對象進行格式化的情況下是可能的 JMFMovieScreen使用的ImageComponent D對象以以下方式聲明 ImageComponent D ic = new ImageComponent D(ImageComponent D FORMAT_RGB FORMAT_SIZE FORMAT_SIZE true true);構(gòu)造器剩余兩個需要說明的討論點是它使用 by reference 和 Y up 模式 這些模式降低了存儲結(jié)構(gòu)圖像的內(nèi)存大小 因為Java D避免將圖像從應(yīng)用空間拷貝到圖形內(nèi)存 在Windows OS環(huán)境下 使用OpenGL作為Java D優(yōu)先圖像引擎 ImageComponent D格式應(yīng)是ImageComponent D FORMAT_RGB BufferedImage格式應(yīng)是BufferedImage TYPE_ BYTE_BGR BufferedImage格式在JMFSnapper中確定 此項技術(shù)的更多細節(jié)可以在中查詢 將紋理加進區(qū)域通常在一個區(qū)域中確定一幅圖像的方法是將圖像的坐下角連接到區(qū)域的左下角 然后逆時針連接剩余的幾個角 圖 說明這種方法 圖 圖像與區(qū)域之間的標準連接 圖像坐標區(qū)間在X Y軸的 之間 Y軸正方向 例如 圖像左下點坐標為( ) 右上點為( ) 當(dāng) Y up 模式使用 圖像坐標Y軸翻轉(zhuǎn) 負方向 意味著( )代表圖像左上點 ( )指向右下 當(dāng) Y up 模式建立 圖像坐標必須分配給區(qū)域中不同點以便獲得圖像的相同定位 圖 顯示了最新配置 圖 Y up 模式使用時 圖像與區(qū)域之間的連接 連接區(qū)域點與圖像定位的JMFMovieScreen編碼是TexCoord f q = new TexCoord f();q set( f f);plane setTextureCoordinate( q);// ( ) tex coord top left quad point (p )q set( f f);plane setTextureCoordinate( q);// ( ) top right (p )q set( f f);plane setTextureCoordinate( q);// ( ) bottom right (p )q set( f f);plane setTextureCoordinate( q);// ( ) bottom left (p )PLANE對象指代區(qū)域 更新圖像以上所講 TimeBehavior是被設(shè)置用來被 毫秒調(diào)用JMFMovieScreen的nextFrame()方法 nextFrame()調(diào)用JMFSnapper對象中的getFrame()方法獲得被看作BufferedImage對象的當(dāng)前動畫幀 指派給一個mageComponent D對象 然后傳給區(qū)域圖像 nextFrame()是 // globalsprivate Texture D texture;// used by the quadprivate ImageComponent D ic;private JMFSnapper snapper;// to take snaps of the movieprivate boolean isStopped = false;// is the movie stopped?public void nextFrame(){ if (isStopped) // movie has been stoppedreturn; BufferedImage im = snapper getFrame();// get current frame if (im != null) { lishixinzhi/Article/program/Java/hx/201311/26618
import?java.awt.Canvas;
import?java.awt.Color;
import?java.awt.Dimension;
import?java.awt.EventQueue;
import?java.awt.Frame;
import?java.awt.Graphics;
import?java.awt.Graphics2D;
import?java.awt.Image;
import?java.awt.RenderingHints;
import?java.awt.event.KeyEvent;
import?java.awt.event.KeyListener;
import?java.awt.event.WindowAdapter;
import?java.awt.event.WindowEvent;
import?java.awt.image.BufferedImage;
import?java.io.File;
import?java.io.IOException;
import?javax.imageio.ImageIO;
public?class?TestImage?extends?Frame
{
private?static?final?long?serialVersionUID?=?1L;
private?static?boolean?PRESSED?=?false;
private?static?int?pointX?=?0;
private?static?int?pointy?=?200;
private?static?int?RIGHT_GO?=?0;
private?static?int?LEFT_GO?=?0;
private?static?int?DIR?=?0;
private?static?int?ANGLE?=?0;
private?static?int?W?=?50;
private?static?int?H?=?60;
private?_Canvas?canvas?=?null;
public?TestImage?()
{
add?(canvas?=?new?_Canvas?());
setIgnoreRepaint?(true);
requestFocus?();
}
public?class?_Canvas?extends?Canvas?implements?Runnable
{
private?static?final?long?serialVersionUID?=?1L;
private?BufferedImage?bi?=?null;
private?Image?bufferedImage?=?null;
private?Thread?thread?=?null;
private?long?sleepTime?=?10;
public?_Canvas?()
{
try
{
bi?=?ImageIO.read?(new?File?("go.png"));
}
catch?(IOException?e)
{}
setBackground?(Color.BLACK);
requestFocus?();
addKeyListener?(new?KeyListener?()
{
@Override
public?void?keyTyped?(?KeyEvent?e?)
{}
@Override
public?void?keyReleased?(?KeyEvent?e?)
{
RIGHT_GO?=?0;
PRESSED?=?false;
}
@Override
public?void?keyPressed?(?KeyEvent?e?)
{
//?38?40?37?39上下左右
DIR?=?e.getKeyCode?();
PRESSED?=?true;
}
});
}
@Override
public?void?paint?(?Graphics?g?)
{
Graphics2D?g2d?=?(Graphics2D)?g;
g2d.setRenderingHint?(RenderingHints.KEY_INTERPOLATION,?RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage?(rotateImage?(bi.getSubimage?(RIGHT_GO,?LEFT_GO,?W,?H),?ANGLE,?true),?pointX,?pointy,?W,?H,
this);
g2d.dispose?();
}
@Override
public?void?update?(?Graphics?g?)
{
if?(null?==?bufferedImage)
{
bufferedImage?=?createImage?(getWidth?(),?getHeight?());
}
Graphics?bufferedG?=?bufferedImage.getGraphics?();
bufferedG.clearRect?(0,?0,?getWidth?(),?getHeight?());
paint?(bufferedG);
bufferedG.dispose?();
g.drawImage?(bufferedImage,?0,?0,?this);
g.dispose?();
}
public?void?start?()
{
thread?=?new?Thread?(this);
thread.setName?("TestImage");
thread.setPriority?(Thread.MIN_PRIORITY);
thread.start?();
}
public?synchronized?void?stop?()
{
thread?=?null;
notify?();
}
@Override
public?void?run?()
{
Thread?me?=?Thread.currentThread?();
while?(thread?==?me??!isShowing?()?||?getSize?().width?==?0)
{
try
{
Thread.sleep?(555);
}
catch?(InterruptedException?e)
{
return;
}
}
while?(thread?==?me??isShowing?())
{
if?(PRESSED)
{
try
{
if?(DIR?==?39)
{
RIGHT_GO?=?RIGHT_GO?+?50;
LEFT_GO?=?0;
pointX?=?pointX?+?1;
if?(pointX??420)
{
ANGLE?=?90;
pointX--;
pointy--;
W?=?60;
H?=?50;
}
if?(RIGHT_GO??50)
{
RIGHT_GO?=?0;
}
}
else?if?(DIR?==?37)
{
pointX?=?pointX?-?1;
RIGHT_GO?=?RIGHT_GO?+?50;
LEFT_GO?=?60;
if?(pointX??0)
{
ANGLE?=?-90;
pointX++;
pointy--;
W?=?60;
H?=?50;
}
if?(RIGHT_GO??50)
{
RIGHT_GO?=?0;
}
}
else?if?(DIR?==?38)
{
W?=?50;
H?=?60;
pointy?=?150;
ANGLE?=?0;
RIGHT_GO?=?100;
}
else?if?(DIR?==?40)
{
W?=?50;
H?=?60;
ANGLE?=?0;
pointy?=?200;
RIGHT_GO?=?0;
}
Thread.sleep?(sleepTime);
repaint?();
}
catch?(InterruptedException?e)
{
break;
}
}
else
{
RIGHT_GO?=?RIGHT_GO?+?50;
LEFT_GO?=?0;
pointX?=?pointX?+?1;
if?(RIGHT_GO??50)
{
RIGHT_GO?=?0;
}
if?(pointX??500)
{
pointX?=?0;
}
try
{
Thread.sleep?(sleepTime);
repaint?();
}
catch?(InterruptedException?e)
{
break;
}
}
}
thread?=?null;
}
}
/**
?*?旋轉(zhuǎn)圖像為指定角度
?*?
?*?@param?degree
?*?@return
?*/
public?static?BufferedImage?rotateImage?(?final?BufferedImage?image,?final?int?angdeg,?final?boolean?d?)
{
int?w?=?image.getWidth?();
int?h?=?image.getHeight?();
int?type?=?image.getColorModel?().getTransparency?();
BufferedImage?img;
Graphics2D?graphics2d;
(?graphics2d?=?(?img?=?new?BufferedImage?(w,?h,?type)?).createGraphics?()?).setRenderingHint?(
RenderingHints.KEY_INTERPOLATION,?RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2d.rotate?(d???-Math.toRadians?(angdeg)?:?Math.toRadians?(angdeg),?w?/?2,?h?/?2);
graphics2d.drawImage?(image,?0,?0,?null);
graphics2d.dispose?();
return?img;
}
public?static?void?main?(?String[]?args?)
{
EventQueue.invokeLater?(new?Runnable?()
{
@Override
public?void?run?()
{
final?TestImage?ti?=?new?TestImage?();
ti.setSize?(new?Dimension?(500,?300));
ti.setLocationRelativeTo?(null);
ti.addWindowListener?(new?WindowAdapter?()
{
@Override
public?void?windowClosing?(?WindowEvent?e?)
{
System.exit?(0);
}
@Override
public?void?windowDeiconified?(?WindowEvent?e?)
{
ti.canvas.start?();
}
@Override
public?void?windowIconified?(?WindowEvent?e?)
{
ti.canvas.stop?();
}
});
ti.setResizable?(false);
ti.canvas.start?();
ti.setVisible?(true);
}
});
}
}