平滑的渐变背景动画java

时间:2017-08-10 02:06:02

标签: java swing

我试图为JPanel设置动画渐变背景。效果有效,但我想在它再次启动时获得平滑过渡。以下是我目前的实施情况。当xvalue2达到极限设置时,我交换颜色并重新开始。

public class GradientAnimation {
static class GradientPanel extends JPanel {
    private static final long serialVersionUID = -4185583782901846967L;
    private Timer timer;
    private float Xend;
    private final float MAXVALUE = 800f;
    private Color color1 = new Color(128,62,153,255);
    private Color color2 = new Color(192,201,200,255);

    GradientPanel() {
        Xend = 0f;
        setOpaque(true);
        ActionListener action = new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent evt){
                if (Xend < MAXVALUE) Xend+=2f;
                else{
                    Color aux = color1;
                    color1 = color2;
                    color2 = aux;
                    Xend = 0f;
                }

                revalidate();
                repaint();
            }   
        };
        timer = new Timer(5, action);
        timer.start();
    }
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;
        final BufferedImage image = new BufferedImage(
                getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
        g2d = image.createGraphics();
        GradientPaint prim = new GradientPaint(0f, 0f, color1,
                Xend, 0f, color2);

        g2d.setPaint(prim);
        g2d.fillRect(0, 0, getWidth(), getHeight());

        g.drawImage(image, 0, 0, null);
    }
}

private static void createAndShowUI() {
    try {
        JFrame frame = new JFrame("Gradient Animation");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);

        GradientPanel imagePanel = new GradientPanel();

        frame.add(imagePanel);
        frame.setSize(400, 400);
        frame.setVisible(true);
    } 
    catch (Exception e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) {

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowUI();
        }
    });
    }
}

同样,我想隐藏我交换颜色的时刻,以获得完美的渐变动画循环。如果代码看起来正确,请告诉我,如何提高质量。

1 个答案:

答案 0 :(得分:4)

在下面的变体中,

  • 使用Color.getHSBColor()循环显示可用的色调;因为色调值环绕,通过光谱的过渡是平滑的。或者,在结束点更改delta的符号。

  • 覆盖getPreferredSize()以建立初始面板几何图形。

  • 不要不必要地缓冲渲染。

  • 不要不必要地重新验证组件。

image

  

我如何调整它以避免在所有颜色中循环?

无尽的变化是可能的;关键问题是避免突然变化。在此,HUE_MINHUE_MAX缩小为频谱的一部分,delta的符号在端点处发生更改,其他HSB组件也会更新。

private static final float HUE_MIN = 4f/6;
private static final float HUE_MAX = 5f/6;
…
    @Override
    public void actionPerformed(ActionEvent evt) {
        hue += delta;
        if (hue > HUE_MAX) {
            hue = HUE_MAX;
            delta = -delta;
        }
        if (hue < HUE_MIN) {
            hue = HUE_MIN;
            delta = -delta;
        }
        color1 = Color.getHSBColor(hue, 1, 1);
        color2 = Color.getHSBColor(hue, 3f/4 + delta, 3f/4 + delta);
        repaint();
    }

image

代码:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

/** @see https://stackoverflow.com/q/45603312/230513 */
public class GradientAnimation {

    static class GradientPanel extends JPanel {

        private static final int WIDE = 640;
        private static final int HIGH = 240;
        private static final float HUE_MIN = 0;
        private static final float HUE_MAX = 1;
        private final Timer timer;
        private float hue = HUE_MIN;
        private Color color1 = Color.white;
        private Color color2 = Color.black;
        private float delta = 0.01f;

        GradientPanel() {
            ActionListener action = new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent evt) {
                    hue += delta;
                    if (hue > HUE_MAX) {
                        hue = HUE_MIN;
                    }
                    color1 = Color.getHSBColor(hue, 1, 1);
                    color2 = Color.getHSBColor(hue + 16 * delta, 1, 1);
                    repaint();
                }
            };
            timer = new Timer(10, action);
            timer.start();
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            GradientPaint p = new GradientPaint(
                0, 0, color1, getWidth(), 0, color2);
            g2d.setPaint(p);
            g2d.fillRect(0, 0, getWidth(), getHeight());
        }

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

    private static void createAndShowUI() {
        JFrame frame = new JFrame("Gradient Animation");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GradientPanel imagePanel = new GradientPanel();
        frame.add(imagePanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowUI();
            }
        });
    }
}