扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
效果图
目前成都创新互联公司已为上1000家的企业提供了网站建设、域名、网络空间、网站改版维护、企业网站设计、濉溪网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
参考代码
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);
//设置定时器, 每隔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();
}
}
一: 用多线程播放一组图片, 实现动画片的效果; 类似于逐帧动画,每个图片是动画的一帧
二: 在awt/swing界面里, 可以使用paint方法,去绘制图形,然后用swing提供的Timer或者多线程技术,去刷新绘制的图形
三:在JavaFX里, 本身就支持动画,并且封装了很多动画效果可以直接使用,比如逐帧动画.缩放动画,渐变动画,旋转动画,位置动画等.
强烈推荐使用javaFX来实现动画, 因为javaFX是现代化的图形界面工具,具有简单,强大,组件丰富,跨平台,支持Html5, 支持表格, 支持动画等多种优势
下面是一个javaFX绘制的动态表格
javaFX动态表格
在Java D场景中插入动画片段使 D内容更加有趣充实 一段动画可以在更令人信服的背景下展示 例如飘动的云 繁忙的城市街道 或者是从窗向外看的效果 动画可以在屏幕效果和游戏效果之间任意转换 这篇文章被分为两个部分 描写我怎样实现一个Java D动画屏幕效果 在这个部分 我将说明我怎样利用JMF(Java Media Framework) 特别是在JMF Performance Pack for Windows v e情况下 我的另外两个工具是J SE 和Java D 我将讨论另外的使用Quicktime for Java的动画屏幕版本 图 是应用JMF Movie D在不同时间截取的两幅截屏 右边截屏是从屏幕后看的效果 图 Movie D应用截屏 此应用程序中重点 JMF和Java D的集成 屏幕以任意尺寸成倍增加在一个应用程序 由于屏幕是Java D的Shape D类的一个子类 因此它可以很容易的统一到各种Java D场景中 程序执行使用Model View Controller设计模式 屏幕是一个视频元素 由JMFMovieScreen类描述 动画是一个由JMFSnapper类控制的模型部分 一个Java D Behavior类 TimeBehavior 控制动画定时定期更新 所有JMF编码都存放在JMFSnapper类 可以很方便的测试各种变化 这篇文章的第二部分JMFSnapper由QuickTime for Java版本中的QTSnapper取代 Java D 的使用将会使动画的播放速度毫无困难的上升到 帧/秒 使用JMF出现问题的讨论 问题是我首选解决方案将不会工作 JMF有可能变为一个巨大的API 但在其内部仍有一些程序没有及时运行 我坐在山上 事实上 我正坐在一个冰冷的办公室 我真正的意思是说这篇文章建立在大量Java D和JMF背景知识之上 我将不会细致地解释Java D的基础知识 因为它们都可以在O Reilly文章Killer Game Programming in Java(以下简称KGPJ)中找到 例如 图 场景效果图是其第 章中的轻微改良Checkers D的版本实例 我再生了这些编码以生成底版 蓝天和灯光 假如你不想买这本书 没关系 所有篇章的初稿和所有编码都可以在此书的站点查阅 在此文章中 我将会解释我用来从动画中抽取帧的JMF技术 我将不会讨论流媒体或者编码转换 应用简述 动画由JMFSnapper类加载播放 并且不断的循环播放直到被停止 JMFMovieScreen生成动画屏幕 并在底版上控制Java D四边形 图 显示这些类的应用(该场景图说明场景中Java D节点怎样连接在一起) 图 Movie D场景图 图 种的很多细节可以被忽略 此图KGPJ 章中的得Checkers D实例有很多相似之处 只有特殊动画的节点是新的 由于节点关系 JMFMovieScreen和TimeBehavior对象以三角形表示 JMFSnapper对象不属于这张图 但由JMFMovieScreen调用 每 毫秒 TimeBehavior对象调用JMFMovieScreen类中的nextFrame()方法 接下来调用JMFSnapper中的getFrame()方法获取动画中当前播放的帧 由JMFMovieScreen控制成像 TimeBehavior是Java D的Behavior类的子类 它是Java D应用的计时器 它与KGPJ 章中的 D sprites实例中的TimeBehavior类十分相似 观察应用过程的另一种方式就是察看它的UML类图表 图 给出 类中的公共方法被显示 图 Movie D类图表 Movie D的子类JFrame WrapMovie D是JPanel的一个子类 图 展示了WrapMovie D如何构建场景图 和将其译成应用的JPanel 他使用CheckerFloor 和ColouredTiles类构建底版 JMFMovieScreen创建动画屏幕 将其加入场景中 通过创建一个JMFSnapper对象开始动画 TimeBehavior每 毫秒调用JMFMovieScreen中的nextFrame()方法 nextFrame()调用JMFSnapper中的getFrame()得到当前帧 这个例子中的所有编码 此文章的早期版本可以在KGPJ网点查询 准备动画 动画 它的屏幕和更新屏幕的TimeBehavior对象 都是由WrapMovie D中的addMovieScreen()方法创立 // 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()方法调用JMFMovieScreen和TimeBehavior节点间的连接 setSchedulingBounds()激活TimeBehavior节点 创建动画屏幕 JMFMovieScreen是Java D的Shape D类的一个子类 所以必须仔细说明它的外形的几何形状和外观 几何形状是指动画图像的四个边尺寸上成比例 它的最大尺寸(高 宽)必须向构造器仔细说明 这个四方形是垂直的 朝向Z轴正方向 可以在底版的任何位置被定位 四方形外观是双面 允许从前或后观看动画 结构是用双线性插值 可以降低动画图像的像素化 大多数的功能是从KGPJ 章中的FPS(first person shooter)实例中的ImageCsSeries类拷贝而来 ImageCsSeries在一个区域中显示一系列的GIF图片 为了简短起见 我仅描述了JMFMovieScreen与ImageCsSeries的不同特征 高效显示图像动画中的一个帧被转换结构扩大四倍 分为两个步骤 第一步 提供的BufferedImage传给Java D的ImageComponent D对象 然后传给Java D Texture D 区域的图像更新非常快 每秒更新 帧 要求结构更新 次 因此结构有效率的更新非常的重要 这种高效率在利用BufferedImage和ImageComponent D对象进行格式化的情况下是可能的 JMFMovieScreen使用的ImageComponent D对象以以下方式声明 ImageComponent D ic = new ImageComponent D(ImageComponent D FORMAT_RGB FORMAT_SIZE FORMAT_SIZE true true);构造器剩余两个需要说明的讨论点是它使用 by reference 和 Y up 模式 这些模式降低了存储结构图像的内存大小 因为Java D避免将图像从应用空间拷贝到图形内存 在Windows OS环境下 使用OpenGL作为Java D优先图像引擎 ImageComponent D格式应是ImageComponent D FORMAT_RGB BufferedImage格式应是BufferedImage TYPE_ BYTE_BGR BufferedImage格式在JMFSnapper中确定 此项技术的更多细节可以在中查询 将纹理加进区域通常在一个区域中确定一幅图像的方法是将图像的坐下角连接到区域的左下角 然后逆时针连接剩余的几个角 图 说明这种方法 图 图像与区域之间的标准连接 图像坐标区间在X Y轴的 之间 Y轴正方向 例如 图像左下点坐标为( ) 右上点为( ) 当 Y up 模式使用 图像坐标Y轴翻转 负方向 意味着( )代表图像左上点 ( )指向右下 当 Y up 模式建立 图像坐标必须分配给区域中不同点以便获得图像的相同定位 图 显示了最新配置 图 Y up 模式使用时 图像与区域之间的连接 连接区域点与图像定位的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对象指代区域 更新图像以上所讲 TimeBehavior是被设置用来被 毫秒调用JMFMovieScreen的nextFrame()方法 nextFrame()调用JMFSnapper对象中的getFrame()方法获得被看作BufferedImage对象的当前动画帧 指派给一个mageComponent D对象 然后传给区域图像 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;
}
}
/**
* 旋转图像为指定角度
*
* @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);
}
});
}
}
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流