Search code examples
javaswingmousejava-2d

Detecting a mouse hover over an object that is not a JComponent


As the title states, I am trying to detect a mouse hover over an object that is not a JComponent. Right now I have a window with a green JPanel. When you left-click on this JPanel you create a point.

What I am trying to do is to have extra information displayed when I hover over these points. However, I have no idea how to even begin detecting if I am hovering my mouse over a point. I tried looking into the MouseListener interface but I could not find any examples of people using MouseListener with an object. I have only seen people use MouseListener with JComponents. I would preferably like to have this mouse hover detection code in my Point class if possible to keep my code clean.

JPanel Code

class Map extends JPanel implements MouseListener {
    
    public static ArrayList<Point> points = new ArrayList<Point>(); //array for the points
    
    public Map() {
        this.setBackground(Color.green);
        this.setPreferredSize(new Dimension(1280, 720));
        this.addMouseListener(this);
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D graphics = (Graphics2D) g;
        
        drawPoints(graphics);
    }
    
    private void drawPoints(Graphics2D graphics) {
        for(int i = 0; i < points.size(); i++) {
            points.get(i).drawPoint(graphics);
        }
    }
    
    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mousePressed(MouseEvent e) {
        if(e.getButton() == MouseEvent.BUTTON1) { //Left Click
            points.add(new Point(e.getX(), e.getY()));
            repaint();
        }
        else if(e.getButton() == MouseEvent.BUTTON3) { //right click
            
            for(int i = points.size() - 1; i >= 0; i--) { //loop backwards so if points overlap remove the one on top first
                Point current = points.get(i);
                if( Math.abs( e.getX() - current.x ) < current.size/2 && Math.abs( e.getY() - current.y ) < current.size/2 ) {
                    points.remove(i);
                    repaint();
                    break;
                }
            }
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        
    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {
        
    }
    
}

Point Code

public class Point {
    public int x, y;
    public int size = 10;
    
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public Point() {
        this.x = 0;
        this.y = 0;
    }
    
    public void drawPoint(Graphics2D graphics) {
        graphics.setPaint(Color.black);
        graphics.setStroke(new BasicStroke(5));
        graphics.drawOval(x - (size/2), y - (size/2), size, size);
        graphics.setPaint(Color.red);
        graphics.fillOval(x - (size/2), y - (size/2), size, size);
    }
    
    public void drawInfo(Graphics2D graphics) {
        graphics.drawString("test", x, y);
    }
    
}

Solution

  • I had the same issue with a Packet-Tracer-Like program, where I drew rects.

    If they are just points, I would check if the mouse cords are the same as the point cords when the mouse is moved.

    @Override
    public void mouseMoved(MouseEvent e) {
        entered = false;
        
        if(point.x == e.getX() && point.y == e.getY()){
            entered = true;
        }
    }
    

    If although, like in my case, the drawn object has a width and a height, it gets messier.

    @Override
    public void mouseMoved(MouseEvent e) {
        entered = false;
        
        if((e.getX() <= point.x+width) && (e.getX() >= point.x)){
            if((e.getY() <= point.y+height) && (e.getY() >= point.y)){
                entered = true;
            }
        }
    }