Java的动画 [英] Java Animations

查看:132
本文介绍了Java的动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经开始采取在Java制作动画(幻灯片,背景等)的兴趣。我知道,JavaFX是多少这样做的更好,但我只是顽固打扰切换。

I've started to take interest with making animations(slideshows, backgrounds etc) in Java. I know that JavaFX is much better for doing this, but I'm just to stubborn to bother switching over.

下面是我得到那么远。

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class BlurredLightCells extends JPanel {

    private static final long serialVersionUID = 4610174943257637060L;

    private Random random = new Random();

    private ArrayList<LightCell> lightcells;

    private float[] blurData = new float[500];

    public static void main(String[] args) {
        JFrame frame = new JFrame("Swing animated bubbles");
        frame.setSize(1000, 750);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(new BlurredLightCells(60));

        frame.setVisible(true);
    }

    public BlurredLightCells(int amtOfBCells) {
        setSize(1000, 750);
        /**
         * Below we initiate all the cells that are going to be drawn on screen
         */
        Arrays.fill(blurData, 1f / 20f);
        lightcells = new ArrayList<LightCell>(amtOfBCells);
        for (int i = 0; i < amtOfBCells; i++) {

            /**
             * Below we generate all the values for each cell(SHOULD be random for each one)
             */
            int baseSpeed = random(0, 3);
            int xSpeed = (int) Math.floor((Math.random() * (baseSpeed - -baseSpeed + baseSpeed)) + -baseSpeed);
            int ySpeed = (int) Math.round((Math.random() * baseSpeed) + 0.5);
            int radius = random(25, 100);
            int x = (int) Math.floor(Math.random() * getWidth());
            int y = (int) Math.floor(Math.random() * getHeight());
            int blurrAmount = (int) (Math.floor(Math.random() * 10) + 5);
            int alpha = (int) ((Math.random() * 15) + 3);

            /**
             * Now we draw a image, and apply transparency and a slight blur to it
             */
            Kernel kernel = new Kernel(blurrAmount, blurrAmount, blurData);
            BufferedImageOp op = new ConvolveOp(kernel);
            BufferedImage circle = new BufferedImage(150, 150, BufferedImage.TYPE_INT_ARGB);
            Graphics2D circlegfx = circle.createGraphics();
            circlegfx.setColor(new Color(255, 255, 255, alpha));
            circlegfx.fillOval(20, 20, radius, radius);
            circle = op.filter(circle, null);
            LightCell bubble = new LightCell(x, y, xSpeed, ySpeed, radius, getDirection(random.nextInt(3)), circle);
            lightcells.add(bubble);
        }
    }

    public int random(int min, int max) {
        final int n = Math.abs(max - min);
        return Math.min(min, max) + (n == 0 ? 0 : random.nextInt(n));
    }

    @Override
    public void paint(Graphics g) {
        int w = getWidth();
        int h = getHeight();
        final Graphics2D g2 = (Graphics2D) g;
        GradientPaint gp = new GradientPaint(-w, -h, Color.LIGHT_GRAY, w, h, Color.DARK_GRAY);
        g2.setPaint(gp);
        g2.fillRect(0, 0, w, h);
        long start = System.currentTimeMillis();
        for (int i = 0; i < lightcells.size(); i++) {
            LightCell cell = lightcells.get(i);
            cell.process(g2);
        }
        System.out.println("Took " + (System.currentTimeMillis() - start) + " milliseconds to draw ALL cells.");
        repaint();
    }

    public String getDirection(int i) {
        switch (i) {
            case 0:
                return "right";
            case 1:
                return "left";
            case 2:
                return "up";
            case 3:
                return "down";
        }
        return "";
    }

    private class LightCell {

        private int x, y, xSpeed, ySpeed, radius;
        private String direction;
        private BufferedImage image;

        public LightCell(int x, int y, int xSpeed, int ySpeed, int radius, String direction, BufferedImage image) {
            this.x = x;
            this.y = y;
            this.xSpeed = xSpeed;
            this.ySpeed = ySpeed;
            this.radius = radius;
            this.direction = direction;
            this.image = image;
        }

        public void process(Graphics g) {
            switch (direction) {
                case "right":
                    moveRight();
                    break;
                case "left":
                    moveLeft();
                    break;
                case "up":
                    moveUp();
                    break;
                case "down":
                    moveDown();
                    break;
            }
            g.drawImage(image, x, y, null);
        }

        private void moveUp() {
            x += xSpeed;
            y -= ySpeed;
            if (y + (radius / 2) < 0) {
                y = getHeight() + (radius / 2);
                x = (int) Math.floor(Math.random() * getWidth());
            }

            if ((x + radius / 2) < 0 || (x - radius / 2) > getWidth()) {
                y = radius + (radius / 2);
                x = (int) Math.floor(Math.random() * getWidth());
            }
        }

        private void moveDown() {
            x += xSpeed;
            y += ySpeed;
            if (y - (radius / 2) > getHeight()) {
                y = 0 - (radius / 2);
                x = (int) Math.floor(Math.random() * getWidth());
            }

            if ((x + radius / 2) < 0 || (x - radius / 2) > getWidth()) {
                y = getHeight() + (radius / 2);
                x = (int) Math.floor(Math.random() * getWidth());
            }
        }

        private void moveRight() {
            x += ySpeed;
            y += xSpeed;
            if (y - (radius / 2) > getHeight() || y + (radius / 2) < 0) {
                x = 0 - (radius / 2);
                y = (int) Math.floor(Math.random() * getHeight());
            }

            if ((x - radius / 2) > getWidth()) {
                x = 0 - (radius / 2);
                y = (int) Math.floor(Math.random() * getWidth());
            }
        }

        private void moveLeft() {
            x -= ySpeed;
            y -= xSpeed;
            if (y - (radius / 2) > getHeight() || y + (radius / 2) < 0) {
                x = getWidth() + (radius / 2);
                y = (int) Math.floor(Math.random() * getHeight());
            }

            if ((x + radius / 2) < 0) {
                x = getWidth() + (radius / 2);
                y = (int) Math.floor(Math.random() * getWidth());
            }
        }
    }
}

如果您运行,你会看到电池的举动以非常高的速度,如果你看看通过code,你看我叫重绘()油漆方法,其中我重写。我知道那并不好做。但我的问题是,是他们,我可以画重绘()循环我现在外面每一个细胞的任何其他方式,因为这会导致其他部件闪烁/当我使用这与其他组件一个JFrame闪烁。

If you run that, you will see the cells move at a very high speed, and if you look through the code, you see I call repaint() in the paint method in which I override. I know thats not good to do. But my question is, is their any other way in which I could draw each cell outside of the repaint() loop I have right now, because that causes other components to flash/flicker when I use this in a JFrame with other components.

FYI:Aventually我想实现类似于这样:<一href=\"http://activeden.net/item/background-animation-blurry-light-cells/21980?WT.ac=category_item&WT.seg_1=category_item&WT.z_author=ranfirefly\"相对=nofollow称号=点击我>点击这里

FYI: Aventually I'd like to achieve something similar to this: Click Here

谢谢!

推荐答案

<击>闪烁的问题是与事实顶层容器不是双缓冲的事。而不是从的JFrame 延伸(或其他顶层容器),你应该考虑使用更多的东西,比如的JP​​anel 并重写它的的paintComponent

The issue of flicker is to do with the fact that top level containers are not double buffered. Instead of extending from JFrame (or other top level containers), you should consider using something more like JPanel and override it's paintComponent.

NB-在我的头上有它的OP从的JFrame ...

nb- Had it in my head that the OP was extending from JFrame...

两个问题可能会造成闪烁。首先是覆盖油漆,二是没有要求 super.paint(G)和更新之间的时间。一个更好的解决办法是重写的paintComponent ,并确保您所呼叫 super.paintComponent方法。也使用类似一个 javax.swing.Timer中的计划更新和定期也将有助于...

Two issues could be causing the flickering. The first is overriding paint, the second is not calling super.paint(g) and the time between the updates. A better solution would be to override paintComponent and make sure you are calling super.paintComponent. Also using something like a javax.swing.Timer to schedule updates and regular intervals would also help...

只能拨打重绘当你想鼓励的RepaintManager 更新你的组件。不要叫重绘任何 paintXxx 方法中,这将导致涂料的请求安排到无休止的循环事件队列,最终consuiming你的CPU

Only call repaint when you want to encourage the RepaintManager to update you component. Don't call repaint from within any paintXxx method, this will cause a never ending loop of paint requests to schedule onto the event queue, eventually consuiming your CPU

我会避免做你的 paintXxx 方法,任何可能需要一段时间才能完成,这会减慢渲染过程。相反,我会使用 javax.swing.Timer中的简单的更新或更复杂的处理过程中,这可能在使用之前它呈现给屏幕更新模型

I would avoid doing anything in your paintXxx methods that might take time to perform, this will slow down the rendering process. Instead, I would use a javax.swing.Timer for simple updates or for more complicated processing, a Thread which could be used to update the model before it is rendered to the screen.

这是一个<一个href=\"http://stackoverflow.com/questions/14886232/swing-animation-running-extremely-slow/14902184#14902184\">example一些简单的优化过程中我也拿500对象的动画,4500只在整体性能会有所沦落。

This is an example of some simple optimisation process I did to take animation of 500 objects to 4500 with only a slight degration in the overall performance.

更新

我改变了你code轻微并能正常工作...

I changed you code slight and it works fine...

我改变了你的油漆方法的paintComponent 并添加 super.paintComponent方法(G)

I changed your paint method to paintComponent and added super.paintComponent(g)

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    int w = getWidth();
    int h = getHeight();
    final Graphics2D g2 = (Graphics2D) g;
    GradientPaint gp = new GradientPaint(-w, -h, Color.LIGHT_GRAY, w, h, Color.DARK_GRAY);
    g2.setPaint(gp);
    g2.fillRect(0, 0, w, h);
    for (int i = 0; i < lightcells.size(); i++) {
        LightCell cell = lightcells.get(i);
        cell.process(g2);
    }
}

而在你的构造函数,我添加结束...

And at the end of your constructor I added...

Timer timer = new Timer(40, new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        repaint();
    }
});
timer.start();

要定期基地更新UI ...

To update the UI on a regular bases...

这篇关于Java的动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆