【问题标题】:Detecting a mouse hover over an object that is not a JComponent检测鼠标悬停在不是 JComponent 的对象上
【发布时间】:2021-08-10 13:32:40
【问题描述】:

正如标题所述,我试图检测鼠标悬停在不是 JComponent 的对象上。 现在我有一个带有绿色 JPanel 的窗口。当您左键单击此 JPanel 时,您会创建一个点。

我想要做的是在我将鼠标悬停在这些点上时显示额外的信息。但是,我什至不知道如何开始检测我是否将鼠标悬停在某个点上。我尝试查看 MouseListener 界面,但找不到任何使用 MouseListener 和对象的示例。我只见过有人将 MouseListener 与 JComponents 一起使用。如果可能的话,我希望在我的 Point 类中包含这个鼠标悬停检测代码,以保持我的代码干净。

JPanel 代码

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

点代码

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

【问题讨论】:

  • 我能想到的一件事是跟踪你的点在组件内的实际坐标,然后实现一个MouseMotionListener,它通过比较鼠标上的坐标来检查鼠标是否悬停在该点上mouseMoved 事件。
  • MouseMotionListener 添加到面板。 mouseMoved(..) 方法在这里很重要。调用该方法后,检查事件所指的点是否在“靠近”任何兴趣点的形状内。通过“形状”和“接近”,我会想到一个 Ellipse2D,它有一个 contains(x,y) 方法。

标签: java swing mouse java-2d


【解决方案1】:

我在类似 Packet-Tracer 的程序中遇到了同样的问题,我在其中绘制了矩形。

如果它们只是点,我会检查鼠标线是否与移动鼠标时的点线相同。

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

如果像我的例子一样,绘制的对象有一个宽度和一个高度,它会变得更乱。

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

【讨论】:

  • 由于无论如何“点”都是使用drawOval 绘制的,因此维护Ellipse2D 列表而不是Point 将是直截了当的。然后,它不再是混乱了,删除点击的对象就像if(points.removeIf(o -&gt; o.contains(e.getX(), e.getY()))) repaint(); 一样简单。然后,将draw(Shape)fill(Shape) 与相同的列表一起使用将使代码保持一致,甚至独立于实际形状。
猜你喜欢
  • 2014-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-09
  • 1970-01-01
  • 2016-12-15
  • 1970-01-01
  • 2014-06-26
相关资源
最近更新 更多