Domanda

I'm feeling quite stupid. But what is the reason why this simple piece of code doesn't change the ellipse's color?

Basically I want to add a mouse listener to the oval - a graphic object. when the mouse cursor is in oval, the oval changes its color. But this code doesn't change at all... This code is for testing only.

public class Help extends JFrame{

    public static void main(String [] agrs){
        Help h = new Help();
        h.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        h.add(new Help_Option());
        h.setSize(2000, 1000);
        h.setVisible(true);
    }
}

class Help_Option extends JComponent implements MouseListener{
    Ellipse2D ellipse = new Ellipse2D.Double(0, 0, 1000, 500);
    Color c = Color.BLACK;    

    public Help_Option(){
        this.addMouseListener(this);
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;

        g2d.setColor(Color.BLUE);
        g2d.draw(ellipse);

        g2d.setColor(c);
        g2d.fill(ellipse);        
    }

    public void setColor(Color c){
        this.c = c;
    }

    @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 (ellipse.contains(e.getX(), e.getY()) ) {
            setColor(Color.GREEN);
            repaint();
        }
    }

    @Override
    public void mouseExited(MouseEvent e) {

    }
}
È stato utile?

Soluzione

you are adding a MouseListener and waiting for mouseEntered events. These are fired when the mouse enters a Component, not a region of it. Try entering the component's boundary where the ellipse is shown and observe.

What you need is a MouseMotionListener, so that you can observe the mouse pixel by pixel; use the mouseMoved or mouseDragged events.

You might still need to listen for mouseEntered or mouseExited events, as MouseMotionEvents are only fired while inside the component's boundary, so you might miss the mouse exiting the component while still inside the ellipse.

A good and simple way for debugging this is adding prints inside the event handler. You would then see that the handler was called, but only once or a few times, and not when you move the mouse within the component.


class Help_Option extends JComponent implements MouseListener, MouseMotionListener {
    Ellipse2D ellipse = ...;

    public Help_Option() {
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
    }

    public void mouseMoved(MouseEvent e) {
        if (ellipse.contains(e.getX(), e.getY()) ) {
            //mouse is inside the ellipse
        } else {
            //mouse is outside the ellipse
        }
    }

    public void mouseExited(MouseEvent e) {
        //mouse is outside the ellipse
    }

    //more method stubs
}

Altri suggerimenti

..if i use the boundary of the ellipse, it would be a rectangle, so whenever my mouse enter the rectangle-but-not-in-ellipse, the color will change

See:

  • Shape.contains(x,y): Tests if the specified coordinates are inside the boundary of the Shape, as described by the definition of insideness.
  • Shape.contains(Point2D): Tests if a specified Point2D is inside the boundary of the Shape, as described by the definition of insideness.

See also this answer for a demo showing collisions between 2 shapes.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top