Java,在 JApplet 中为静止图像制作动画

Java, animate a still image in a JApplet

我正在做一项作业,我基本上已经完成了这项作业,它只是一个简单的程序,用于创建图像映射并向热点添加一些音频,我还有几天时间,我正在做尝试 "animate" 图像。

这是一张汽车仪表板的图片,当用户点击点火开关时,我想看看是否有办法让图像抖动一秒钟。我试过在这里和 google 上四处寻找,但每次搜索时,我得到的都是 90 年代关于 applet 而不是 JApplet 的文章。

如果您能为我指明如何 "animate" 图片的正确方向,或者甚至指向可能有教程的地方,我将不胜感激!

如果你想看看我在说什么并且无论如何都可以帮助我,这是我的代码。

public class ImageMap extends JApplet implements MouseListener{
   private Image pic;
   private Container contentPane;
   private JLabel directions;
   private Rectangle horn;
   private Rectangle vent;
   private Rectangle doorLocksUpper;
   private Rectangle window;
   private Rectangle radio;
   private Rectangle ignition;
   private int x, y;
   private AudioClip hornSound, airSound, radioClip, lockSound1, lockSound2, ignitionSound;

public void init() {        
    pic = getImage(getCodeBase(), "CarDash.jpg");
    horn = new Rectangle(250, 142, 105,104);
    vent = new Rectangle(514, 159, 204, 72);
    doorLocksUpper = new Rectangle(80, 167, 104, 58);
    window = new Rectangle(122, 243, 88, 55);
    radio = new Rectangle(514, 234, 176, 171);
    ignition = new Rectangle(465, 217, 42, 43);

    directions = new JLabel("CLICK ON: Horn, Door Locks, Air Vents, Radio & Ignition Push Start");

    //Create components
    contentPane = getContentPane();
    contentPane.setLayout(new FlowLayout());
    contentPane.add(directions, BorderLayout.NORTH);
    contentPane.addMouseListener(this);
}


//Display image on applet window
public void paint(Graphics g) {
    g.drawImage(pic, 0, 40, this);

}

public void mouseClicked(MouseEvent me) {
    //Play horn clip when car horn is clicked.
    if(horn.contains(me.getX(), me.getY())) {
        play(getCodeBase(), "HornSound.wav");
    }
    if(vent.contains(me.getX(), me.getY())) {
        play(getCodeBase(), "AirVent.wav");
    }
    if(ignition.contains(me.getX(), me.getY())) {
        play(getCodeBase(), "Ignition.wav");
    }
    if(doorLocksUpper.contains(me.getX(), me.getY())) {
        play(getCodeBase(), "DoorLocks.wav");
    }
    if(radio.contains(me.getX(), me.getY())) {
        play(getCodeBase(), "BrownSugar.mid");
    }
    if(window.contains(me.getX(), me.getY())) {
        play(getCodeBase(), "Window.wav");
    }
}
public void mouseReleased(MouseEvent me) {}
public void mouseEntered(MouseEvent me) {}
public void mouseExited(MouseEvent me) {}
public void mousePressed(MouseEvent me) {}
}

这里有一个非常快速和有用的提示,不要像小程序一样直接绘制到顶级容器。它将您困在一个单一的用例中,这并不总是使修改或重用变得更容易。

相反,首先使用 JPanel 之类的东西作为您的主要容器,有了这个,您可以将它添加到任何您喜欢的东西,小程序,window,其他一些容器。

虽然有多种方法可以在 Swing 中制作动画,但最简单(通常也是最安全)的方法之一是使用 Swing Timer

这个例子简单地使用了一个 Swing Timer,设置为每 16 毫秒更新一次(这对于我的捕获软件来说已经快了 :P),当你点击面板时它就会启动。计时器只是更新一个偏移值,该偏移值隔离正值和负值。 Timer 利用 LocalTime 计算 Timer 的时间长度 运行 在一秒后停止

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.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalTime;
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 ShakeAnimation {

    public static void main(String[] args) {
        new ShakeAnimation();
    }

    public ShakeAnimation() {
        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 ShakePane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class ShakePane extends JPanel {

        private Timer timer;
        private LocalTime startTime;
        private int xOffset = 0;
        private int delta = 8;

        private BufferedImage img;

        public ShakePane() {
            try {
                img = ImageIO.read(getClass().getResource("Duke-Thumbs.jpg"));
            } catch (IOException exp) {
                exp.printStackTrace();
            }
            timer = new Timer(16, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Duration duration = Duration.between(startTime, LocalTime.now());
                    if (duration.getSeconds() >= 1) {
                        timer.stop();
                        xOffset = 0;
                    } else {
                        xOffset *= -1;
                    }
                    repaint();
                }
            });
            addMouseListener(new MouseAdapter() {

                @Override
                public void mouseClicked(MouseEvent e) {
                    if (!timer.isRunning()) {
                        xOffset = delta;
                        startTime = LocalTime.now();
                        timer.start();
                    }
                }

            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (img != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                int x = ((getWidth() - img.getWidth()) / 2) + xOffset;
                int y = (getHeight() - img.getHeight()) / 2;
                g2d.drawImage(img, x, y, this);
                g2d.dispose();
            }
        }

    }

}

有关详细信息,请参阅 How to use Swing Timers