简体   繁体   English

Java2d中的动画图像

[英]Animate Image in Java2d

im learning Java2d, and im trying to animate my image in x coordinate using a Timer, but is not working, the idea is between a time frame the image x value increments a value making it to move, can someone figure out what is the problem in my code? 我正在学习Java2d,并尝试使用Timer在x坐标中为我的图像设置动画,但没有用,这个想法是在图像x值增加一个使其移动的时间范围内,有人可以找出问题所在吗?在我的代码中?

Here is the code: 这是代码:

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;
    }

}

Two main things: 两件事:

  1. The delay is small 延迟小
  2. The change is large 变化很大

This means that the object can be moved out side of the visible bounds quickly, usually quicker then the screen can be realized on the screen. 这意味着可以将对象快速移出可见范围之外,通常比在屏幕上实现屏幕更快。

You could play with the timing, but, animation is the illusion of change over time, you may find it better to reduce the size of the change rather the then the delay (although 100fps might be asking a bit much ;)) 您可以按时播放,但是动画是随着时间变化的幻觉,您可能会发现减小更改的大小会更好,而不是延迟(尽管100fps可能会要求很多;)

There is also no bounds checking, so the object is free to move off the viewable area, this might be desirable, but probably would have at least hinted towards the problem you were having. 也没有边界检查,因此对象可以自由移出可见区域,这可能是合乎需要的,但可能至少暗示了您遇到的问题。

As Swing is not thread safe (you shouldn't update the UI from outside the context of the EDT), you are also running the risk of inuring a thread race condition. 由于Swing并不是线程安全的(您不应从EDT上下文外部更新UI),因此也存在确保线程竞争条件的风险。 In this example, it would probably be very hard to do, but the concept of how you are changing the state is dangerous. 在此示例中,可能很难做到,但是如何更改状态的概念很危险。

Because Swing uses a passive rendering engine, a paint cycle may occur at anytime, without your interaction or knowledge, so you should be careful updating variables which the paint methods need to render the state outside of the context of the EDT. 由于Swing使用被动渲染引擎,因此涂漆循环可能会随时发生,而无需您的交互或不了解,因此您应谨慎更新涂漆方法需要在EDT上下文之外渲染状态的变量。

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;
        }
    }

}

This simple example uses a Swing Timer as the primary engine, it reduces the amount of change (to 2 ) as well as adds bounds checking 这个简单的示例使用Swing Timer作为主要引擎,它减少了更改量(到2 )并添加了边界检查

Take a look at Concurrency in Swing and How to use Swing Timers for more details 查看Swing中的并发性如何使用Swing计时器以了解更多详细信息

Your code is working, but you are updating too fast. 您的代码正在运行,但是更新太快。

Try 尝试

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

To check your animation. 检查动画。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM