【问题标题】:Smooth gradient background animation java平滑渐变背景动画java
【发布时间】:2017-08-10 02:06:02
【问题描述】:

我正在尝试为 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();
        }
    });
    }
}

再次,我想隐藏我交换颜色以获得完美的渐变动画循环的那一刻。请让我知道代码是否正确以及如何提高质量。

【问题讨论】:

  • 请不要发布关于填充的废话,因为这违背了限制的目的,并且对我们这些会帮助你的志愿者不公平。相反,请告诉您问题的详细信息,代码的作用,它应该做什么。
  • 是的,我明白了。但是与代码相比,我的解释太短了,我想发布一个工作代码而不是 sn-p 以便可以对其进行测试。对不起。
  • 所以补充说明,不废话。帮助我们了解您编写的代码,描述它。同样,您对我们的帮助只会对您有所帮助。
  • 改写一下,我这样做是因为我无法发布带有上述解释的问题,因为我认为我提供了足够的详细信息和可以尝试的工作代码。

标签: java swing


【解决方案1】:

在下面的变体中,

  • 使用Color.getHSBColor() 在可用色调之间循环;因为色调值环绕,所以光谱的过渡是平滑的。或者,在端点更改delta 的符号。

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

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

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

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

变化无穷;关键问题是避免突然变化。在这里,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();
    }

代码:

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

【讨论】:

  • 这很好用,我将如何调整它以避免在所有颜色之间循环?两种基色而不是全光谱。
  • @SantiagoRosales:我在上面提出了一种方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-14
  • 1970-01-01
  • 2012-06-13
  • 2018-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多