【问题标题】:Java, animate a still image in a JAppletJava,在 JApplet 中为静止图像设置动画
【发布时间】:2015-11-07 01:07:18
【问题描述】:

我正在处理一项任务,我基本上完成了任务,这只是一个简单的程序,用于创建图像映射并为热点添加一些音频,我还有几天时间,我打算试试和“动画”图像。

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

如果你能指出我如何“动画”图像的正确方向,甚至指向可能有教程的地方,我将不胜感激!

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

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) {}
}

【问题讨论】:

    标签: java swing animation japplet


    【解决方案1】:

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

    相反,首先使用JPanel 之类的东西作为您的主要容器,通过它,您可以将其添加到任何您喜欢的东西、小程序、窗口或其他容器中。

    虽然您可以通过多种方式在 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

    【讨论】:

    • 太棒了,感谢您的详细帮助!快速提问。我不明白您的意思是“不要直接绘制到像小程序这样的顶级容器。它会将您困在一个用例中”。当您说使用 JPanel 时,我是否会创建一个像 JFrame 和 JPanel 这样的常规摆动窗口,而您是在谈论使用它而不是 Content Pane?在这种情况下,我会不再使用 Applet Viewer 吗?这个任务希望我们使用 JApplet。我不知道您是否可以使用 JApplet 等 JPanel 的所有摆动组件,以及是否需要扩展 JFrame...
    • 不,在这种情况下,您可以将JPanel 添加到您的任何内容(如JApplet),它只是将责任转移到更好的管理级别。首先,顶级容器(如JApplet)不是双缓冲的,因此您可能会遇到一些闪烁或其他图形故障,并且JApplet(和JFrame)在物理容器之间有JRootPanecontentPane和用户,因为你实际上已经打破了绘画链,这可能会进一步引入图形故障的可能性
    • 感谢疯狂!如果您看到这个并稍等片刻……“您实际上已经破坏了油漆链”是什么意思?
    • 在 Swing 中绘制是通过一系列链式方法调用来执行的,从paint 开始,它调用一系列子方法,而不是调用super.paint,你实际上已经绕过了这个系统并且打破油漆链。由于绘画的工作方式,在某些情况下(例如鼠标悬停),子组件可以独立于父容器进行绘画,这可能会导致无穷无尽的怪异。
    猜你喜欢
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    • 2013-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多