Java Swing Jbutton:仅在悬停时显示边框和背景

Java Swing Jbutton:仅在悬停时显示边框和背景,java,swing,hover,jbutton,Java,Swing,Hover,Jbutton,我想在自定义Swing.JButton中添加一个悬停效果,类似于Chrome浏览器上的图标: 悬停前>> 悬停后>> 创建按钮时,我可以将其设置为“之前”状态,但悬停时,我无法创建“边框+凸起背景”。当我尝试将边框重新添加到按钮时,我得到了一种移动效果,就像重新绘制新边框后插入的效果一样 这是我当前的代码: public class MyButton extends JButton implements MouseListener { public MyButton(String icon

我想在自定义Swing.JButton中添加一个悬停效果,类似于Chrome浏览器上的图标:

悬停前>>

悬停后>>

创建按钮时,我可以将其设置为“之前”状态,但悬停时,我无法创建“边框+凸起背景”。当我尝试将边框重新添加到按钮时,我得到了一种移动效果,就像重新绘制新边框后插入的效果一样

这是我当前的代码:

public class MyButton extends JButton implements MouseListener {

public MyButton(String iconPath, String toolTip) {
    super(new ImageIcon(TipButton.class.getResource(iconPath)));
    addMouseListener(this);
    setBorder(null);
    setBorderPainted(false);
    setFocusPainted(false);
    setOpaque(false);
    setContentAreaFilled(false);
    setToolTipText(toolTip);
}

public MyButton(String iconPath, String name, String toolTip) {
    this(observers, iconPath, toolTip);
    setText(name);
}

@Override
public void mouseClicked(MouseEvent e) {}

@Override
public void mousePressed(MouseEvent e) {}

@Override
public void mouseReleased(MouseEvent e) {}

@Override
public void mouseEntered(MouseEvent e) {
    if (e.getSource() != this) return;

    setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
}

@Override
public void mouseExited(MouseEvent e) {
    if (e.getSource() != this) return;

    setBorder(null);
}

}

我想主要的逻辑应该是mouseenterned/mouseexitted方法,但我不知道如何获得想要的效果。有什么想法吗?

对每个州使用不同的图像。您可以为选定、禁用选定、禁用、按下、滚动、滚动启用、滚动选择设置不同的图标。更多信息。

在java 7中,有一个BevelOrder类,看起来就是您要查找的。您可能会感兴趣的两种方法是

    paintRaisedBevel(Component c, Graphics g, int x, int y, int width, int height)

以下是有关该类的文档:

  • (可能)没有理由创建
    扩展JButton实现MouseListener{
    ,没有重载任何
    JButton
    的方法,而是使用带返回的组合

  • 最好是创建一个局部变量并使用API中实现的方法

  • 不要使用,所有这些事件都在中正确实现

  • 最简单的方法是使用
    JButton.getModel
    from


我想我已经找到了一个解决方案。使用具有相同大小的凸起边框(插图)的EmptyBorder可以解决问题。代码:

public class SwingUtils {

public static JButton createMyButton (String iconPath, String toolTip) {
    final JButton b = new JButton (new ImageIcon(SwingUtils.class.getResource(iconPath)));
    final Border raisedBevelBorder = BorderFactory.createRaisedBevelBorder();
    final Insets insets = raisedBevelBorder.getBorderInsets(b);
    final EmptyBorder emptyBorder = new EmptyBorder(insets);
    b.setBorder(emptyBorder);
    b.setFocusPainted(false);
    b.setOpaque(false);
    b.setContentAreaFilled(false);
    b.setToolTipText(toolTip);
    b.getModel().addChangeListener(new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
            ButtonModel model = (ButtonModel) e.getSource();
            if (model.isRollover()) {
                b.setBorder(raisedBevelBorder);
            } else {
                b.setBorder(emptyBorder);
            }
        }
    });
    return b;
}

}

注意:正如mKorbel所说,它将使用ChangeListener和在工厂方法中创建的按钮,而不是子类JButton。

目前,我正试图避免为每个按钮制作额外的图像,并试图以编程方式获得效果。+1,我喜欢这个想法,(尽管我的投票将在10小时后进行),因为我今天已经达到极限:(.这里有一个相关的我喜欢你的建议,但为什么不简单:button.setboorder(BorderFactory.createBevelOrder(BevelOrder.RAISED/lower)),注意是的,我真的认为createBevelOrder(int)是一个简单的想法,效果也一样好,但根据Randomize的代码,他一直在尝试,而且一直存在问题,所以我只是提供了一个替代解决方案,他可能会更成功。啊哈,我的错,以前没有发现:(,尽管这将是一项棘手的任务,通过子类化BevelOrder来实现,因为您指定的方法具有受保护的访问说明符,尽管+1,但正如前面所说,可能需要时间才能将虚拟转换为物理:-)是的,他真的应该尝试获取CreateBevelOrder()工作。我尽量避免子类化,并采取阻力最小的方式:)。这只会增加混乱,正如你所说,转换它很可能需要更多的时间。我实际上是在谈论我的投票,这将需要时间,因为我昨天的限值已经过了:-)但是,为什么需要继承
JButton
,在我看来,代码是不存在的。正如
mKorbel
所建议的那样,这整件事也可以在
JButton
的一个实例上完成(这就是为什么对答案投了赞成票)我希望你会考虑构图继承,在代码的实际实现中。移除继承,用ChangeListener替换MouseListener。
public class SwingUtils {

public static JButton createMyButton (String iconPath, String toolTip) {
    final JButton b = new JButton (new ImageIcon(SwingUtils.class.getResource(iconPath)));
    final Border raisedBevelBorder = BorderFactory.createRaisedBevelBorder();
    final Insets insets = raisedBevelBorder.getBorderInsets(b);
    final EmptyBorder emptyBorder = new EmptyBorder(insets);
    b.setBorder(emptyBorder);
    b.setFocusPainted(false);
    b.setOpaque(false);
    b.setContentAreaFilled(false);
    b.setToolTipText(toolTip);
    b.getModel().addChangeListener(new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
            ButtonModel model = (ButtonModel) e.getSource();
            if (model.isRollover()) {
                b.setBorder(raisedBevelBorder);
            } else {
                b.setBorder(emptyBorder);
            }
        }
    });
    return b;
}

}