Reputation: 149
I'm trying to create a mouseOver visual effect for several JLabel elements filled with text. The idea is to make each label darker when mouse enters and then return it to normal when the mouse leaves its area. Also all the labels are placed over a panel that has a background image.
Though simple enough, I've encountered a nasty behavior I can't overcome.
Bug 1: The first time I move mouse over a label it shows me the upper-left corner of my main window as its background.
Bug 2: Then, every time I move mouse over one label once, and then move it over the second label, the second one changes its background to the "summ background" (panel image + semitransparent background) of first label. Above that it seems that even the first label's text contents are being "copied" to the second label's background. This only happened once per label change: if I move mouse over the same label twice, the second mouse over event is painted correctly.
I've already tried to use MouseMotionListener, a different element (JButton), played with component modification methods and eve tried to override paint methods. No result.
I've attached an animated GIF showing the described behavior: Two JLabels copying backgrounds and contents from each other
I'm relatively new to Swing so I'm not familiar with its caveats. Any idea what might cause this?
Custom Panel class:
public class ImagePanel extends JPanel{
private static final long serialVersionUID = -3995745756635082049L;
private Image image = null;
public ImagePanel(Image image){
this.image = image;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
if(image != null){
g.drawImage(image, 0, 0, this);
}
}
}
MouseListener class:
public class MouseHoverPiece implements MouseListener{
private static final Cursor CURSOR_HAND = new Cursor(Cursor.HAND_CURSOR);
private static final Cursor CURSOR_DEFAULT = new Cursor(Cursor.DEFAULT_CURSOR);
private static final Color HOVER_SHADOW = new Color(40, 80, 60, 50);
@Override
public void mouseEntered(MouseEvent e) {
JLabel component = (JLabel)e.getComponent();
component.setBackground(HOVER_SHADOW);
component.setCursor(CURSOR_HAND);
component.setOpaque(true);
component.repaint();
}
@Override
public void mouseExited(MouseEvent e) {
JLabel component = (JLabel)e.getComponent();
component.setBackground(null);
component.setCursor(CURSOR_DEFAULT);
component.setOpaque(false);
component.repaint();
}
MainWindow class:
Image background = ResourceLoader.loadImage("board.png");
ImagePanel panel = new ImagePanel(background);
panel.setBounds(10, 55, 480, 480);
panel.setLayout(null);
panel_main.add(panel);
final JLabel lblNewLabel1 = new JLabel("N");
lblNewLabel1.setHorizontalAlignment(SwingConstants.CENTER);
lblNewLabel1.setOpaque(false);
lblNewLabel1.setBounds(25, 24, 52, 52);
lblNewLabel1.setFont(lblNewLabel1.getFont().deriveFont(42f));
lblNewLabel1.addMouseListener(new MouseHoverPiece());
panel.add(lblNewLabel1);
final JLabel lblNewLabel2 = new JLabel("O");
lblNewLabel2.setHorizontalAlignment(SwingConstants.CENTER);
lblNewLabel2.setOpaque(false);
lblNewLabel2.setBounds(25+52+2, 24, 52, 52);
lblNewLabel2.setFont(lblNewLabel2.getFont().deriveFont(42f));
lblNewLabel2.addMouseListener(new MouseHoverPiece());
panel.add(lblNewLabel2);
Upvotes: 0
Views: 163
Reputation: 149
I think I've found the solution. Both bugs had disappeared. What I did was to add parent container's (in my case the panel with the board background) repaint:
@Override
public void mouseEntered(MouseEvent e) {
JLabel component = (JLabel)e.getComponent();
component.setBackground(HOVER_SHADOW);
component.setCursor(CURSOR_HAND);
component.setOpaque(true);
Container container = component.getParent();
component.repaint();
container.repaint(); //fix
}
@Override
public void mouseExited(MouseEvent e) {
JLabel component = (JLabel)e.getComponent();
component.setBackground(null);
component.setCursor(CURSOR_DEFAULT);
component.setOpaque(false);
Container container = component.getParent();
component.repaint();
container.repaint(); //fix
}
Thanks everyone for your help ;)
Upvotes: 0
Reputation: 324207
private static final Color HOVER_SHADOW = new Color(40, 80, 60, 50);
Swing components have problems with transparent backgrounds because you are breaking the painting rules which state that an opaque component will completely paint the background.
Check out Backgrounds With Transparency for more information and a couple of solutions to the problem. You can either:
Upvotes: 2