Java2d中的动画图像

时间:2015-06-22 22:56:19

标签: java image swing animation java-2d

我正在学习Java2d,并且我试图使用Timer在x坐标中为我的图像设置动画,但是不起作用,这个想法是在时间帧之间,图像x值增加一个值使其移动,有人可以找出什么是我的代码中的问题?

以下是代码:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class Screen extends JPanel {
    int posX;
    Timer timer;
    private BufferedImage image;

    public Screen() {
        setDoubleBuffered(true);
        posX = 1;
        timer = new Timer();
        timer.scheduleAtFixedRate(new Anima(), 100, 10);

        //Smile Icon
        try{
            image = ImageIO.read(getClass().getResource("/smily.png"));
        }catch(IOException e){

            e.printStackTrace();        
        }  

    }
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(image,this.posX,100,null);


    }

    class Anima extends TimerTask{

        public void run() {

            posX += 20;
            repaint();      

        }

    }

    public void incMove() {
        posX += 20;
    }

}

2 个答案:

答案 0 :(得分:1)

两件主要的事情:

  1. 延迟很小
  2. 变化很大
  3. 这意味着对象可以快速移出可见边界的一侧,通常更快,然后屏幕就可以在屏幕上实现。

    你可以玩时间,但是,动画是随着时间的推移变化的幻觉,你可能会发现减少变化的大小而不是延迟(尽管100fps可能会要求更多;))

    也没有边界检查,因此对象可以自由地移出可视区域,这可能是可取的,但可能至少暗示了你遇到的问题。

    由于Swing不是线程安全的(您不应该从EDT的上下文之外更新UI),因此您也存在确定线程争用情况的风险。在这个例子中,它可能很难做到,但是你如何改变状态的概念是危险的。

    因为Swing使用被动渲染引擎,所以在没有您的交互或知识的情况下,可能会随时发生绘制周期,因此您应该小心更新绘制方法在EDT上下文之外呈现状态所需的变量。 / p>

    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Screen extends JPanel {
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new Screen());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        private int posX;
        private int delta = 2;
    
        public Screen() {
            setDoubleBuffered(true);
            posX = 1;
    
            Timer timer = new Timer(10, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    incMove();
                    repaint();
                }
            });
            timer.start();
    
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
            Graphics2D g2d = (Graphics2D) g;
            g2d.drawRect(this.posX, 100, 10, 10);
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }
    
        public void incMove() {
            posX += delta;
            if (posX + 10 > getWidth()) {
                posX = getWidth() - 10;
                delta *= -1;
            } else if (posX < 0) {
                posX = 0;
                delta *= -1;
            }
        }
    
    }
    

    这个简单的示例使用Swing Timer作为主要引擎,它减少了更改量(到2)以及添加边界检查

    请查看Concurrency in SwingHow to use Swing Timers了解详情

答案 1 :(得分:0)

您的代码正常运行,但您的更新速度过快。

尝试

timer.scheduleAtFixedRate(new Anima(), 100, 1000);

检查动画。