基于MIDP1.0实现动画效果

无感无刷电机三段式启动避坑指南:从预定位到闭环切换的STM32代码实现 本文深入解析无感无刷电机的三段式启动流程,涵盖预定位、启动加速与闭环切换三大阶段。重点对比了恒频升压、恒压升频与升频升压三种核心启动策略的优劣,并提供了基于STM32的详细状态机代码实现与关键参数调试指南,帮助工程师有效规避启动失步、线圈过热等常见问题,实现稳定可靠的无感驱动。 阅读详情
        在SUN的技术文章里面有一篇文章讲述了如何基于MIDP1.0实现动画,个人觉得很不错。在MIDP1.0中并为直接对动画提供支持,如果我们明白动画的原理,熟悉Timer和TimerTask的话实现动画并非很困难的事情。

       动画实际上就是一系列连续的帧,当他们变换的足够快的时候,我们人的眼睛就会觉得他是运动的。所以如果我们能够周期性的切换画面,从第一帧到第二帧到第三帧 ......那么我们就可以制作出动画的效果了。Timer和TimerTask正好可以很好的帮我们完成这一功能,如果你还不熟悉这两个类可以参考使用Java中的Timer和TimerTask。我们首先扩展TimerTask实现AnimatedImage类,它的功能就是在特定位置画图

import java.util.*;
import javax.microedition.lcdui.*;

// Defines an animated image, which is just a set
// of images of equal size which are drawn in turn
// to simulate movement.

public class AnimatedImage extends TimerTask
{
    private Canvas canvas;
    private Image[] images;
    private int[][] clipList;
    private int current;
    private int x;
    private int y;
    private int w;
    private int h;

    // Construct an animation with no canvas.

    public AnimatedImage(Image[] images)
    {
        this(null, images, null);
    }

    // Construct an animation with a null clip list.

    public AnimatedImage(Canvas canvas, Image[] images)
    {
        this(canvas, images, null);
    }

    // Construct an animation. The canvas can be null, but
    // if not null then a repaint will be triggered on it
    // each time the image changes due to a timer event.
    // If a clip list is specified, the image is drawn
    // multiple times, each time with a different clip
    // rectangle, to simulate transparent parts.

    public AnimatedImage(Canvas canvas, Image[] images, int[][] clipList)
    {
        this.canvas = canvas;
        this.images = images;
        this.clipList = clipList;

        if (images != null && clipList != null)
        {
            if (clipList.length < images.length)
            {
                throw new IllegalArgumentException();
            }
        }

        if (images != null && images.length > 0)
        {
            w = images[0].getWidth();
            h = images[0].getHeight();
        }
    }

    // Move to the next frame, wrapping if necessary.

    public void advance(boolean repaint)
    {
        if (++current >= images.length)
        {
            current = 0;
        }

        if (repaint && canvas != null && canvas.isShown())
        {
            canvas.repaint(x, y, w, h);
            canvas.serviceRepaints();
        }
    }

    // Draw the current image in the animation. If
    // no clip list, just a simple copy, otherwise
    // set the clipping rectangle accordingly and
    // draw the image multiple times.

    public void draw(Graphics g)
    {
        if (w == 0 || h == 0)
            return;

        int which = current;

        if (clipList == null || clipList[which] == null)
        {
            g.drawImage(images[which], x, y, g.TOP | g.LEFT);
        } else
        {
            int cx = g.getClipX();
            int cy = g.getClipY();
            int cw = g.getClipWidth();
            int ch = g.getClipHeight();

            int[] list = clipList[which];

            for (int i = 0; i + 3 <= list.length; i += 4)
            {
                g.setClip(x + list[0], y + list[1], list[2], list[3]);
                g.drawImage(images[which], x, y, g.TOP | g.LEFT);
            }

            g.setClip(cx, cy, cw, ch);
        }
    }

    // Moves the animation's top left corner.

    public void move(int x, int y)
    {
        this.x = x;
        this.y = y;
    }

    // Invoked by the timer. Advances to the next frame
    // and causes a repaint if a canvas is specified.

    public void run()
    {
        if (w == 0 || h == 0)
            return;

        advance(true);
    }
}

我们需要预先在jar文件里面存储几个大小一样,形态有序的图片,在MIDlet启动的时候把它装载在一个Image数组,并把它作为参数传递给AnimatedImage。
private Image[] loadFrames( String name, int frames )
                                  throws IOException {
    Image[] images = new Image[frames];
    for( int i = 0; i < frames; ++i ){
 images[i] = Image.createImage( name + i +
            ".png" );
    }

    return images;
}

Image[] frames = loadFrames( "/images/bird", 7 );
AnimatedImage ai = new AnimatedImage( frames );
ai.move( 20, 20 ); // set top-left to 20,20

下面是两个测试效果的AnimatedCanvas和AnimationTest类的源代码,在这里你可以得到全部的源文件和图片资源。仔细读读这几个类是很有好处的。有一点值得一提的是,在绘制图片的时候应该判断设备是否支持双缓冲,如果不支持要使用双缓冲技术避免画面闪烁。而且我们也不适宜把动画图片作的过大,这样会增大jar文件的大小,同时会给设备造成很大的负担。

    protected void paint(Graphics g)
    {
        Graphics saved = g;

        if (offscreen != null)
        {
            g = offscreen.getGraphics();
        }

        g.setColor(255, 255, 255);
        g.fillRect(0, 0, getWidth(), getHeight());

        int n = images.size();
        for (int i = 0; i < n; ++i)
        {
            AnimatedImage img = (AnimatedImage) images.elementAt(i);
            img.draw(g);
        }

        if (g != saved)
        {
            saved.drawImage(offscreen, 0, 0, Graphics.LEFT | Graphics.TOP);
        }
    }

import java.io.*;
import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

// MIDlet that displays some simple animations.
// Displays a series of birds on the screen and
// animates them at different (random) rates.

public class AnimationTest extends MIDlet implements CommandListener
{

    private static final int BIRD_FRAMES = 7;
 private static final int NUM_BIRDS = 5;

    private Display display;
    private Timer timer = new Timer();
    private AnimatedImage[] birds;
    private Random random = new Random();

    public static final Command exitCommand = new Command("Exit", Command.EXIT,
            1);

    public AnimationTest()
    {
    }

    public void commandAction(Command c, Displayable d)
    {
        if (c == exitCommand)
        {
            exitMIDlet();
        }
    }

    protected void destroyApp(boolean unconditional)
            throws MIDletStateChangeException
    {
        exitMIDlet();
    }

    public void exitMIDlet()
    {
        timer.cancel(); // turn it off...
        notifyDestroyed();
    }

    // Generate a non-negative random number...

    private int genRandom(int upper)
    {
        return (Math.abs(random.nextInt()) % upper);
    }

    public Display getDisplay()
    {
        return display;
    }

    // Initialize things by creating the canvas and then
    // creating a series of birds that are moved to
    // random locations on the canvas and attached to
    // a timer for scheduling.

    protected void initMIDlet()
    {
        try
        {
            AnimatedCanvas c = new AnimatedCanvas(getDisplay());
            Image[] images = loadFrames("/images/bird", BIRD_FRAMES);

            int w = c.getWidth();
            int h = c.getHeight();

            birds = new AnimatedImage[NUM_BIRDS];
            for (int i = 0; i < NUM_BIRDS; ++i)
            {
                AnimatedImage b = new AnimatedImage(c, images);
                birds[i] = b;
                b.move(genRandom(w), genRandom(h));
                c.add(b);
                timer.schedule(b, genRandom(1000), genRandom(400));
            }

            c.addCommand(exitCommand);
            c.setCommandListener(this);

            getDisplay().setCurrent(c);
        } catch (IOException e)
        {
            System.out.println("Could not load images");
            exitMIDlet();
        }
    }

    // Load the bird animation, which is stored as a series
    // of PNG files in the MIDlet suite.

    private Image[] loadFrames(String name, int frames) throws IOException
    {
        Image[] images = new Image[frames];
        for (int i = 0; i < frames; ++i)
        {
            images[i] = Image.createImage(name + i + ".png");
        }

        return images;
    }

    protected void pauseApp()
    {
    }

    protected void startApp() throws MIDletStateChangeException
    {
        if (display == null)
        {
            display = Display.getDisplay(this);
            initMIDlet();
        }
    }
}


import java.util.*;
import javax.microedition.lcdui.*;

// A canvas to which you can attach one or more
// animated images. When the canvas is painted,
// it cycles through the animated images and asks
// them to paint their current image.

public class AnimatedCanvas extends Canvas
{
    private Display display;
    private Image offscreen;
    private Vector images = new Vector();

    public AnimatedCanvas(Display display)
    {
        this.display = display;

        // If the canvas is not double buffered by the
        // system, do it ourselves...

        if (!isDoubleBuffered())
        {
            offscreen = Image.createImage(getWidth(), getHeight());
        }
    }

    // Add an animated image to the list.

    public void add(AnimatedImage image)
    {
        images.addElement(image);
    }

    // Paint the canvas by erasing the screen and then
    // painting each animated image in turn. Double
    // buffering is used to reduce flicker.

    protected void paint(Graphics g)
    {
        Graphics saved = g;

        if (offscreen != null)
        {
            g = offscreen.getGraphics();
        }

        g.setColor(255, 255, 255);
        g.fillRect(0, 0, getWidth(), getHeight());

        int n = images.size();
        for (int i = 0; i < n; ++i)
        {
            AnimatedImage img = (AnimatedImage) images.elementAt(i);
            img.draw(g);
        }

        if (g != saved)
        {
            saved.drawImage(offscreen, 0, 0, Graphics.LEFT | Graphics.TOP);
        }
    }
}


< p>
下载igv报错:Error loading genome hg38raw.githubusercontent.com...如何解决? 🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值 。 阅读详情

相关推荐

西安电子科技大学841学长经验分享(总成绩第三名)

西安电子科技大学841学长经验分享(总成绩第三名)

qq_30953547的博客 1082

基于MIDP1.0实现通信录

作者:mingjava  文章来源:http://www.j2medev.com/Article/ShowArticle.asp?ArticleID=41项目简介      基于MIDP1.0实现的个人通信录是我在学习MIDP子系统Record Management System的时候自己编写的应用程序,整个应用程序涉及到MIDP的高级和低级API、应用MVC实现界面导航、RMS的高级应用、多线程

mobilechannel的专栏 940

从Power到HO:一文搞懂主流脑图谱在DPABI里怎么选,让你的rs-fMRI分析更精准

本文深入解析了rs-fMRI分析中主流脑图谱(如Power、HO、AAL等)在DPABI中的科学选择策略,帮助研究者根据不同的神经科学研究目标优化分析流程。从解剖学图谱到功能连接图谱的特性对比,到DPABI实操中的多图谱分析工作流,提供了全面的方法论指导,助力提升静息态功能磁共振成像(rs-fMRI)研究的精准度和可重复性。

weixin_30654583的博客 403

在MIDP1.0下实现图片翻转

    我们知道,MIDP1.0中并没有提供图片翻转的功能。但是在MIDP2.0中,我们可以利用Sprite的setTransform(int transform)方法来达到目的。在该方法中,transform参数的取值范围为8个常量之一,这8个常量分别是:    Sprite.TRANS_MIRROR:让精灵左右镜像变换    Sprite.TRANS_MIRROR_ROT180: 让精灵左右镜

Stone的专栏 2390

钢铁雄心4存档修改全攻略:从基础设置到高级玩法(附国家代码表)

本文详细解析《钢铁雄心4》存档修改技巧,从基础设置到高级玩法全覆盖。包括存档文件位置、格式转换、国家实力调整、国际关系修改等实用内容,并附赠国家代码表。掌握存档修改技能,解锁游戏全部潜力,实现精细参数控制,超越控制台指令的局限。

weixin_29233857的博客 1431

ABAP代码使用OAuth2.0 Client Credential调用外部API

ABAP-OAuth2.0-调用外部API

m0_74015269的博客 1956

midp1.0动画

在SUN的技术文章里面有一篇文章讲述了如何基于MIDP1.0实现动画,个人觉得很不错。在MIDP1.0中并为直接对动画提供支持,如果我们明白动画的原理,熟悉Timer和TimerTask的话实现动画并非很困难的事情。    动画实际上就是一系列连续的帧,当他们变换的足够快的时候,我们人的眼睛就会觉得他是运动的。所以如果我们能够周期性的切换画面,从第一帧到第二帧到第三帧 ......那么我们就可

335

机械臂电机力矩计算

设计 6 轴机械臂时,电机力矩计算是确保机械臂负载能力、运动精度和安全性的核心环节,需围绕和两大核心展开,结合机械臂结构参数(如关节长度、质量分布)、负载需求(如末端负载重量、惯性)和运动参数(如加速度、角速度)逐步推导。

ZPC8210的博客 1856

MIDP中的动画

作者:Eir Giguere 编译:Sean 使用MIDP(Mobile Information Device Profile)的开发人员经常会抱怨用些什么办法才可以在一个MIDlet上显示动画。 MIDP 1.0 没有直接提供对动画的支持(正在开发中的MIDP 2.0支持),但真要是自己去实现,其实也并非是一件很难的事。 任何动画的最基本的前提,是要在足够快的时间内显示和更换一张张的图片,让人的

gdsean的专栏 922

一文讲透 .claude/ 文件夹:Claude Code 团队配置指南和最佳实践

本文系统梳理了ClaudeCode配置框架,旨在解决实际落地中的常见困惑。文章从五层作用域体系(组织策略、命令行参数、本地覆盖、项目级、用户级)切入,详细解析了CLAUDE.md、rules、skills、agents等核心组件的定位与配合关系。重点强调了"确定性规则"与"概率性建议"的分层设计:权限控制和安全边界应通过settings.json和hooks实现,而工作约定和编码规范适合放在CLAUDE.md。文中提供了可直接套用的最小配置方案,并总结了10大常见踩坑

974

【Java开发者必看】LangChain4j实战指南:使用AIService轻松集成聊天记忆Chat Memory到SpringBoot应用,通过封装多轮复杂对话,使聊天记忆的实现变得简单

聊天记忆是指在与用户的多轮对话过程中,能够记住之前的交互内容,从而提供更加连贯和个性化的回复。LangChain4j支持通过ChatMemoryProvider接口实现聊天记忆功能。

Spring Boot-Common On With You 448

用J2ME在移动设备上实现动画

使用MIDP(Mobile Information Device Profile)的开发人员经常会抱怨用些什么办法才可以在一个MIDlet上显示动画。MIDP 1.0 没有直接提供对动画的支持(MIDP 2.0支持),但真要是自己去实现,其实也并非是一件很难的事。   任何动画的最基本的前提,是要在足够快的时间内显示和更换一张张的图片,让人的眼睛看到动的画面效果。图片必须按照顺序画出来。从一张图片

Legion.Tao(http://t.sina.com.cn/dastantao) 648

大数据预测分析:精准把握市场趋势

传统市场预测多依赖经验判断(比如“去年卖了1000件,今年加20%”)或小数据统计(比如用近6个月的销量做线性回归)。而大数据预测分析是:利用海量结构化+非结构化数据(销售、用户、社交媒体、天气等),通过机器学习/深度学习模型,挖掘数据中的关联关系与趋势规律,实现对未来市场走势的精准预测。更全面:覆盖内部(企业数据)+外部(行业、环境数据)的全维度数据;更精准:用算法替代人工,避免主观偏差;更实时:支持分钟级/小时级的实时预测(比如直播带货的销量预测)。错误做法。

AI智能探索者的博客 1024

MIDP2.0 Game API简介

MIDP 2.0 为移动开发者带来几项新特性,比如支持媒体、更好的用户界面、新的连通协议、enabled push、空中下载和更好的安全性。然而一个最让人感兴趣的新特性就是GAME API。这篇文章重点介绍GAME API里的新类和它们的用法,开发环境使用J2ME Wireless Toolkit 2.0 Beta。The Game APIThe Game API 帮助开发者(游戏开发者或其他想得

冷枫@优快云 2935

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

AprilGameEngine_MIDP1.0

AprilGameEngine_MIDP1.0Author:Tony.MingEmail: yesming@126.comCopy Right by tony.ming 2004版权声明Licence:----------------------------此软件为共享软件,任何个人和单位均可免费复制,拷贝,复制时请注明出处。但如需商业用途或者使用,修改其中的全部或者部分代码,图片。请先和

1872

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

上一篇: 精通J2ME中的Hello World
下一篇: 在MIDP2.0中调用平台服务
mingjava
博客等级 码龄24年 68粉丝 114原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值