javaswingpaintcomponentmouselistenermousehover

How to detect mouse hover on an image drawn from paintComponent's drawImage(); method


I am new to Java and need help. I am making a GUI for an application using images made from photoshop, and want to create a menu using images which highlights when user hover mouse over them. I have tried mouseEntered(); method by getting mouse x, y co-ordinates but it's not working. Here is the code.

public class GUI extends JComponent{

    public void paintComponent(Graphics g){

        super.paintComponent(g);
        ImageIcon exitBtnImg = new ImageIcon("src/images/userInterface/exitBtn.png");
        g.drawImage(exitBtnImg.getImage(), 0, 5, this);
        mouseHandler handler = new mouseHandler();
        addMouseListener(handler);
    }
}


public class mouseHandler implements MouseListener{

    @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.getX()>100&&e.getX()<300)&&(e.getY()>50&&e.getY()<196)){

            repaint();
        }
    }

    @Override
   public void mouseExited(MouseEvent e) {

    }

}

Solution

    1. Don't load resources in paintComponent, your paint method should run as fast as it can
    2. Don't add listeners within the paint methods, this will get called a lot, so you're just repeatedly adding new listeners each time your component is painted
    3. Use a MouseMotionListener instead of a MouseListener, you want the mouseMoved event
    4. You need some way to know where the image is painted, so you can determine if the mouse moved within it's bounds.

    Have a look at How to Write a Mouse-Motion Listener and Painting in AWT and Swing for more details.

    This example uses a simple Rectangle to define the location that the image is painted within, when the mouse moves within the confines of that Rectangle, a flag is set and the component is repainted, which paints a alpha based highlight effect over the image

    Hover

    import java.awt.AlphaComposite;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Example {
    
        public static void main(String[] args) {
            new Example();
        }
    
        public Example() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        try {
                            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                            ex.printStackTrace();
                        }
    
                        JFrame frame = new JFrame("Testing");
                        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                        frame.add(new TestPane());
                        frame.pack();
                        frame.setLocationRelativeTo(null);
                        frame.setVisible(true);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private BufferedImage img;
            private Rectangle drawRectangle;
            private boolean highlight = false;
    
            public TestPane() throws IOException {
                img = ImageIO.read(...);
                addMouseMotionListener(new MouseAdapter() {
    
                    @Override
                    public void mouseMoved(MouseEvent e) {
                        highlight = drawRectangle.contains(e.getPoint());
                        repaint();
                    }
    
                });
    
                int width = getPreferredSize().width;
                int height = getPreferredSize().height;
    
                int x = (width - img.getWidth()) / 2;
                int y = (height - img.getHeight()) / 2;
    
                drawRectangle = new Rectangle(x, y, img.getWidth(), img.getHeight());
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(400, 400);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.drawImage(img, drawRectangle.x, drawRectangle.y, this);
                if (highlight) {
                    g2d.setColor(Color.RED);
                    g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
                    g2d.fill(drawRectangle);
                }
                g2d.dispose();
            }
    
        }
    
    }
    

    Now, having said all that, you might be better off using the rollover capabilities of JButton, which will basically do the same thing.

    See How to Use Buttons, Check Boxes, and Radio Buttons for more details