Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swing Jbutton: showing border and background only when it is hovered

I want to add a hovering-effect to my customized Swing.JButton similar to the icon on my Chrome Browser:

Before hover >>

enter image description here

After hover >>

enter image description here

I am able to set the button in the "before" status when it is created, but I am not able to create the "border + raised-background" when it is hovered. When I try to re-add the border to the button, I got a moving effect as after repainting a new border is inserted.

This is my current code:

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

}

I suppose the main logic should be in the methods mouseEntered/mouseExited but I don't know how to get the wanted effect. Any idea?

like image 959
Randomize Avatar asked Jul 15 '13 15:07

Randomize


People also ask

How do I make the background of a JButton transparent?

JButton can become transparent If the value of the opaque property of a JButton is set to false, the background becomes transparent allowing whatever is behind the button to show through. Only the text and the border of the button remain opaque.

How do I add a border to a JButton?

We can set different borders like LineBorder, BevelBorder, EtchcedBorder, EmptyBorder, TitledBorder, etc to JButton using the setBorder() method of JComponent class.

How do I know if JButton is pressed?

the code will show the "Add button is pressed" message when I press "Checkout" button after I press "Add" button but If the "Add" Button is not pressed before the "Checkout" Button is pressed, the code will show the "Add Button is not pressed" message.

What is subclass of JButton Swing package?

Swing defines four types of buttons: JButton, JToggleButton, JCheckBox, and JRadioButton. All are subclasses of the AbstractButton class, which extends JComponent. Thus, all buttons share a set of common traits.


4 Answers

I think I have found a solution. Using EmptyBorder with the same sizes (insets) of a raised border does the trick. Code:

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

}

Note: as mKorbel says it would be using ChangeListener and the button created in a factory method instead of subclass JButton.

like image 196
Randomize Avatar answered Nov 15 '22 05:11

Randomize


Use different images for every state. You can set a different Icon for selected, disabled selected, disabled, pressed, rollover, rolloverEnabled, rolloverSelected. More info here.

like image 29
Jannis Alexakis Avatar answered Nov 15 '22 07:11

Jannis Alexakis


In java 7 there is a BevelBorder class that looks to be what you are looking for. The 2 methods you will probably be interested in are

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

and

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

Here is the documentation on the class: http://docs.oracle.com/javase/7/docs/api/javax/swing/border/BevelBorder.html

like image 23
Collin Avatar answered Nov 15 '22 05:11

Collin


  • there (maybe) no reason to create extends JButton implements MouseListener {, there aren't overroaded any of JButtons methods, and use composition with returns instead,

  • better could be to create a local variable and to use methods implemented in API

  • don't to use MouseListener for Buttons Components, all these events are implemented in JButtons API and correctly

  • use set(Xxx)Icon for JButton

  • easiest of ways is to use JButton.getModel from ChangeListener, for example

like image 41
mKorbel Avatar answered Nov 15 '22 07:11

mKorbel