Java 有没有一种简单的方法可以将渐变/动画从JButton图标更改为滚动图标?

Java 有没有一种简单的方法可以将渐变/动画从JButton图标更改为滚动图标?,java,jbutton,rollover-effect,Java,Jbutton,Rollover Effect,贝娄是我的一个按钮代码 continueGame = new JButton(""); continueGame.setIcon(new ImageIcon("resources/buttonUI/continueGame.png")); continueGame.setRolloverEnabled(true); continueGame.setRolloverIcon(new ImageIcon("resources/buttonUI/continueGame

贝娄是我的一个按钮代码

    continueGame = new JButton("");
    continueGame.setIcon(new ImageIcon("resources/buttonUI/continueGame.png"));
    continueGame.setRolloverEnabled(true);
    continueGame.setRolloverIcon(new ImageIcon("resources/buttonUI/continueGameOnHover.png"));
    continueGame.setBorderPainted(false);
    continueGame.setContentAreaFilled(false);
    continueGame.setBounds(frameSize.x/2-343/2, (int)((frameSize.y)*0.28), 343, 85);
    continueGame.addActionListener(this);
这工作得非常好,但当我悬停按钮时,它会立即从基本图标变为RolloverIcon。有没有一种方法可以让它们之间有一种淡入淡出或是一种缓慢的变化?

“简单”是主观的

“最大的”问题是试图找出这幅画应该出现在哪里

图标和滚动图标由UI委托绘制。这有点痛苦,因为你真的不想为你可能想要使用的每一种可能的外观和感觉设计一个UI委托

所以,相反,您需要自己接管很多功能

下面的方法基本上使用委托模式来卸载“正常”和“滚动”图标的混合,并相应地设置按钮的
图标
属性(这是一个欺骗)

基本功能由Swing
定时器控制,有关详细信息,请参阅

它是基于时间的,也就是说,它不是在达到某个值之前运行,而是在指定的时间段内运行。这通常会产生更好的动画效果

import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ButtonModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class JavaApplication155 {

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

    public JavaApplication155() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() throws IOException {
            JButton btn = new JButton();
            BufferedImage cat = ImageIO.read(getClass().getResource("cat.png"));
            BufferedImage dog = ImageIO.read(getClass().getResource("dog.png"));

            btn.setIcon(new ImageIcon(cat));
            btn.setRolloverEnabled(true);

            RolloverAnimator animator = new RolloverAnimator(btn, cat, dog);

            setLayout(new GridBagLayout());
            add(btn);
        }

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

    }

    public class RolloverAnimator {

        private JButton btn;
        private BufferedImage normalImage;
        private BufferedImage rolloverImage;

        private double progress;

        private Timer timer;

        private int totalAnimationTime = 300;
        private int animationTime = totalAnimationTime;
        private Long startedAt = null;

        private boolean wasRolledOver = false;

        public RolloverAnimator(JButton btn, BufferedImage normalImage, BufferedImage rolloverImage) {
            this.btn = btn;
            this.normalImage = normalImage;
            this.rolloverImage = rolloverImage;
            ButtonModel model = btn.getModel();
            model.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    if (model.isArmed()) {
                        return;
                    }
                    if (model.isRollover() && !wasRolledOver) {
                        wasRolledOver = true;
                        prepare();
                    } else if (!model.isRollover() && wasRolledOver) {
                        wasRolledOver = false;
                        prepare();
                    }
                }
            });

            timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (startedAt == null) {
                        startedAt = System.currentTimeMillis();
                    }
                    long duration = System.currentTimeMillis() - startedAt;
                    progress = (double) duration / (double) animationTime;
                    if (progress > 1.0) {
                        progress = 1.0;
                        startedAt = null;
                        timer.stop();
                    }
                    BufferedImage target = transition(normalImage, rolloverImage, progress);
                    btn.setIcon(new ImageIcon(target));

                    if (!timer.isRunning()) {
                        progress = 0.0;
                    }
                }
            });
        }

        protected void prepare() {
            if (timer.isRunning()) {
                timer.stop();
                animationTime = (int) ((double) totalAnimationTime * progress);
                startedAt = System.currentTimeMillis() - (totalAnimationTime - (long)animationTime);
            } else {
                animationTime = totalAnimationTime;
                startedAt = null;
            }
            progress = 0.0;

            timer.start();
        }

        public BufferedImage transition(BufferedImage from, BufferedImage to, double progress) {
            int width = Math.max(from.getWidth(), to.getWidth());
            int height = Math.max(from.getHeight(), to.getHeight());
            BufferedImage target = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = target.createGraphics();

            float normalAlpha = wasRolledOver ? 1.0f - (float) progress : (float) progress;
            float rollOverAlpha = wasRolledOver ? (float) progress : 1.0f - (float) progress;

            g2d.setComposite(AlphaComposite.SrcOver.derive(normalAlpha));
            draw(from, target, g2d);
            g2d.setComposite(AlphaComposite.SrcOver.derive(rollOverAlpha));
            draw(to, target, g2d);
            g2d.dispose();
            return target;
        }

        protected void draw(BufferedImage img, BufferedImage on, Graphics2D g2d) {
            int xPos = (img.getWidth() - on.getWidth()) / 2;
            int yPos = (img.getHeight() - on.getHeight()) / 2;
            g2d.drawImage(img, xPos, yPos, btn);
        }
    }

}

“简单”是主观的-你可能需要实现你自己的
按钮模型
,也可能需要你自己的UI委托才能让它工作是的,我想我必须使用这种技术。使用受控alpha…混合两层图像。。。。我只是没想到会有这么多军国主义的代码。感谢您的帮助,这试图解决的“问题”是,如果用户在动画进行过程中离开(或进入)会发生什么(基本上改变方向)