首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java Swing中的JButton悬停动画

问Java Swing中的JButton悬停动画
EN

Stack Overflow用户
提问于 2018-08-18 05:43:36
回答 1查看 2.6K关注 0票数 2

我工作在图形用户界面窗口与Swing,我想创建一个导航菜单。当鼠标悬停在导航菜单的按钮上时,我想给它们添加一个动画。

像这样的东西:

​

​

我不能使用鼠标侦听器,因为它只是在没有动画的情况下在颜色之间切换,就像这样

​

​

翻滚需要gif,不同的屏幕大小需要不同的gif大小。

有没有办法做到这一点呢?如何抛出代码?

EN

回答 1

Stack Overflow用户

发布于 2018-08-19 23:16:06

这是一个比MadProgrammer建议的简单得多的实现。它做了一些天真的假设,比如线性颜色插值。它也不会尝试动画颜色的alpha混合。而且它不支持响应键盘导航的动画。

内部Fader类使用javax.swing.Timer在一个方向上制作动画。为每个JMenuItem指定两个渐变对象,一个用于过渡到高光颜色,另一个用于过渡回常规背景颜色。

还有必要重写UI委托对象,因为大多数外观都希望强制使用自己的颜色,而不管JMenuItem的背景是什么,无论是在菜单项始终具有键盘焦点时都是如此。

代码语言:javascript
复制
import java.util.Objects;

import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.Timer;
import javax.swing.plaf.basic.BasicMenuItemUI;

public class FadingMenuTest {
    private static final int animDurationMillis = 500;
    private static final int frameCount = 8;

    private static class Fader {
        private final Component component;

        private final Color normalBackground;
        private final float[] normalRGBA;
        private final float[] targetRGBA;
        private final float[] rgba = new float[4];

        private final Timer timer = new Timer(animDurationMillis / frameCount,
            e -> updateBackground());

        private int frameNumber;

        Fader(Component component,
              Color targetBackground,
              Color normalBackground) {

            this.component = Objects.requireNonNull(component);
            this.normalBackground = normalBackground;
            this.normalRGBA = normalBackground.getComponents(null);
            this.targetRGBA = targetBackground.getComponents(null);
        }

        private void updateBackground() {
            if (++frameNumber > frameCount) {
                timer.stop();
                return;
            }

            for (int i = rgba.length - 1; i >= 0; i--) {
                float normal = normalRGBA[i];
                float target = targetRGBA[i];
                rgba[i] =
                    normal + (target - normal) * frameNumber / frameCount;
            }

            component.setBackground(
                new Color(rgba[0], rgba[1], rgba[2], rgba[3]));
        }

        void start() {
            frameNumber = 0;
            timer.restart();
            component.setBackground(normalBackground);
        }

        void stop() {
            timer.stop();
            component.setBackground(normalBackground);
        }
    }

    static void addFadeOnHover(Component component,
                               Color targetBackground,
                               Color normalBackground) {

        Fader entryFader =
            new Fader(component, targetBackground, normalBackground);
        Fader exitFader =
            new Fader(component, normalBackground, targetBackground);

        component.addMouseListener(new MouseAdapter() {
            private static final long serialVersionUID = 1;

            @Override
            public void mouseEntered(MouseEvent event) {
                exitFader.stop();
                entryFader.start();
            }

            @Override
            public void mouseExited(MouseEvent event) {
                entryFader.stop();
                exitFader.start();
            }
        });
    }

    static void show() {
        Color foreground = Color.WHITE;
        Color background = new Color(0, 0, 128);
        Color highlight = Color.BLUE;

        JPopupMenu menu = new JPopupMenu();
        menu.setBackground(background);

        menu.add(new JMenuItem(String.format("%c Backup", 0x1f5ce)));
        menu.add(new JMenuItem(String.format("%c Screenshots", 0x1f5b5)));
        menu.add(new JMenuItem("\u26ed Settings"));

        // Most look-and-feels will override any colors we set, especially
        // when a menu item is selected.
        BasicMenuItemUI ui = new BasicMenuItemUI() {
            {
                selectionForeground = foreground;
                selectionBackground = background;
            }

            @Override
            public void paintBackground(Graphics g,
                                        JMenuItem item,
                                        Color background) {
                super.paintBackground(g, item, item.getBackground());
            }
        };

        for (Component item : menu.getComponents()) {
            AbstractButton b = (AbstractButton) item;
            b.setContentAreaFilled(false);
            b.setOpaque(true);
            b.setUI(ui);

            item.setForeground(foreground);
            item.setBackground(background);
            addFadeOnHover(item, highlight, background);
        }

        JLabel label = new JLabel("Right click here");
        label.setBorder(BorderFactory.createEmptyBorder(200, 200, 200, 200));
        label.setComponentPopupMenu(menu);

        JFrame frame = new JFrame("Fading Menu Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(label);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> show());
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51903228

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档