首页 > 解决方案 > 如何将 mouseClicked() 与不规则对象一起使用

问题描述

到目前为止,我的 mouseClicked() 方法使用 getX() 和 getY()。查看用户是否点击了肺部图片。然而,通过使用 x 和 y,成功的“区域”是一个盒子,而不是肺的形状。因此,在我的 mouseClicked 方法中单击肺的右侧或左侧也会成功单击。有没有办法可以改变它,只有点击肺部才会产生成功的事件?

提前致谢。

单击左肺的左上角和右下角会在不应该的情况下生成成功事件

标签: javamouseclick-event

解决方案


一个简单的解决方案是使用Graphics 2D 形状 API

这允许您创建任意形状(多边形)并利用它的各种碰撞检测功能来确定鼠标是否移入或移出

例如...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                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);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<Shape> paths;
        private Shape filled;

        public TestPane() {
            double radius = 50;
            double orginX = 100;
            double orginY = 100;
            int dif = (int) (360 / 12d);
            paths = new ArrayList<>(25);

            for (int i = 0; i < 360; i += dif) {
                double angle = Math.toRadians(i);
                double centerX = radius * Math.cos(angle) + orginX;
                double centerY = radius * Math.sin(angle) + orginY;

                Path2D path = new Path2D.Double();
                path.moveTo(radius * Math.cos(angle + Math.toRadians(60)) + centerX, radius * Math.sin(angle + Math.toRadians(60)) + centerY);
                path.lineTo((radius * Math.cos(angle - Math.toRadians(60)) + centerX), (radius * Math.sin(angle - Math.toRadians(60)) + centerY));
                path.lineTo(orginX, orginY);
                paths.add(path);
            }

            addMouseMotionListener(new MouseAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {
                    filled = null;
                    for (Shape path : paths) {
                        if (path.contains(e.getPoint())) {
                            filled = path;
                            break;
                        }
                    }
                    repaint();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
            for (Shape shape : paths) {
                if (shape == filled) {
                    g2.setColor(Color.BLUE);
                    g2.fill(shape);
                }
                    g2.setColor(Color.BLACK);
                g2.draw(shape);
            }
            g2.dispose();
        }
    }
}

推荐阅读