You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现JButton从普通Icon到Rollover Icon的淡入淡出动画切换?

实现Java JButton图标悬停时的淡入淡出切换效果

这个瞬间切换的问题确实挺影响视觉体验的,JButton本身并没有内置这种平滑过渡的功能,但我们可以通过自定义按钮组件结合Swing的Timer来实现淡入淡出的效果。核心思路是逐步改变悬停图标的透明度,让两张图标慢慢混合过渡,具体实现如下:

步骤1:自定义带过渡效果的按钮类

我们需要创建一个JButton的子类,负责处理图标加载、鼠标事件监听以及动画过渡逻辑:

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;

public class FadeButton extends JButton {
    private BufferedImage normalImage;
    private BufferedImage hoverImage;
    private float alpha = 0.0f; // 0.0=完全显示正常图标,1.0=完全显示悬停图标
    private Timer fadeTimer;
    private boolean isHovering = false;
    // 可调整的动画参数
    private static final int ANIMATION_INTERVAL = 10; // 每10ms更新一次状态
    private static final float ALPHA_STEP = 0.05f; // 每次透明度变化的步长

    public FadeButton(String normalIconPath, String hoverIconPath) {
        // 加载图标资源
        try {
            normalImage = ImageIO.read(getClass().getResource(normalIconPath));
            hoverImage = ImageIO.read(getClass().getResource(hoverIconPath));
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 取消按钮默认样式,只显示图标
        setBorderPainted(false);
        setContentAreaFilled(false);
        setFocusPainted(false);
        // 设置按钮大小与图标一致(也可以自定义尺寸)
        setPreferredSize(new Dimension(normalImage.getWidth(), normalImage.getHeight()));

        // 初始化定时器,负责更新透明度并重绘按钮
        fadeTimer = new Timer(ANIMATION_INTERVAL, e -> {
            if (isHovering) {
                alpha = Math.min(alpha + ALPHA_STEP, 1.0f); // 不超过1.0
            } else {
                alpha = Math.max(alpha - ALPHA_STEP, 0.0f); // 不低于0.0
            }
            repaint();
        });

        // 监听鼠标进入/退出事件,触发动画
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                isHovering = true;
                if (!fadeTimer.isRunning()) {
                    fadeTimer.start();
                }
            }

            @Override
            public void mouseExited(MouseEvent e) {
                isHovering = false;
                if (!fadeTimer.isRunning()) {
                    fadeTimer.start();
                }
            }
        });
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();

        // 先绘制基础图标
        g2d.drawImage(normalImage, 0, 0, this);
        // 按当前透明度绘制悬停图标,实现混合效果
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
        g2d.drawImage(hoverImage, 0, 0, this);

        g2d.dispose();
    }
}

步骤2:替换原有按钮代码

把你原来创建continueGame按钮的代码替换成使用我们自定义的FadeButton:

// 替换原有的JButton创建逻辑
FadeButton continueGame = new FadeButton(
    "/resources/buttonUI/continueGame.png",
    "/resources/buttonUI/continueGameOnHover.png"
);
continueGame.setBounds(frameSize.x/2-343/2, (int)((frameSize.y)*0.28), 343, 85);
continueGame.addActionListener(this);
// 把按钮添加到你的容器中(比如JFrame或JPanel)
add(continueGame);

关键细节说明

  • 动画速度调整:你可以修改ANIMATION_INTERVAL和ALPHA_STEP来控制过渡快慢,比如减小ALPHA_STEP并缩短ANIMATION_INTERVAL会让动画更平滑,但不要设置得太极端,避免性能问题。
  • 资源路径:确保图片路径使用getResource的方式读取,这样无论项目是本地运行还是打包成jar都能正确加载资源。
  • 自定义尺寸:如果按钮尺寸和图标不一致,可以在paintComponent里使用drawImage的重载方法指定绘制的宽高,比如g2d.drawImage(normalImage, 0, 0, getWidth(), getHeight(), this)。

内容的提问来源于stack exchange,提问作者user6318284

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:52:55