Java MouseEvent position is inaccurate

社会主义新天地 提交于 2019-11-30 16:56:43

The mouse event is automatically converted to be relative to the component that it occurred in that is, point 0x0 is always the top left corner of the component.

By using RingChart r = ((Canvas)e.getSource()).getParent(), you've effectively changed the reference, which now means the location is no longer valid.

You need to convert the location so that its coordinates are in the context of the parent component. Take a look at SwingUtilities.convertMouseEvent(Component, MouseEvent, Component)

UPDATE with PICTURES

Lets take this example...

The blue box has a relative position of 50px x 50px to the red box. If you click in the blue box, lets say at 25x25, the mouse coordinates will be relative to the blue box (0x0 will be the top left of the blue box).

If you then pass this event to the red box and try and use the coordinates from it, you will find that the coordinates will now be half way between the top left of the red box and the blue box, because the coordinates are context sensitive.

In order to get it to work, you need to translate the mouse events location from the blue box to the red box, which would make it 75x75

Now, I don't know what you're doing when you pass the mouse event to the RingChart so I'm only guessing that this is the issue you're facing.

UPDATED with Click Code

Okay, lets say, you have a Canvas at 100x100. You click on that Canvas at 50x50. You then pass that value back up the chain.

public void mouseClick(MouseEvent evt){
    //evt = SwingUtilities.convertMouseEvent(this, evt, c);
    if(evt.getButton() == MouseEvent.BUTTON1 && animation == null){
        for(Element e : elements){
            // Here, we are asking the shape if it contains the point 50x50...
            // Not 150x150 which would be the relative position of the click
            // in the context to the RingChart, which is where all your objects
            // are laid out.
            // So even the original Canvas you clicked on will return 
            // false because it's position + size (100x100x width x height) 
            // does not contain the specified point of 50x50...
            if(e.getShape() != null && e.getShape().contains(evt.getPoint())){
                //do some stuff
            }
        }
    }
}

UPDATED

I think you have your references around the wrong way...

public static MouseEvent convertMouseEvent(Component source,
                       MouseEvent sourceEvent,
                       Component destination)

I think it should read something like

evt = SwingUtilities.convertMouseEvent(evt.getComponent(), evt, this);

UPDATE with Code Example

Okay, so, I put this little example together...

public class TestMouseClickPoint extends JFrame {

    private ContentPane content;

    public TestMouseClickPoint() throws HeadlessException {

        setSize(600, 600);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        setLayout(new BorderLayout());

        content = new ContentPane();
        add(content);

    }

    protected void updateClickPoint(MouseEvent evt) {
        content.updateClickPoint(evt);
    }

    protected class ContentPane extends JPanel {

        private Point relativePoint;
        private Point absolutePoint;

        public ContentPane() {
            setPreferredSize(new Dimension(600, 600));
            setLayout(null); // For testing purpose only...

            MousePane mousePane = new MousePane();
            mousePane.setBounds(100, 100, 400, 400);

            add(mousePane);
        }

        protected void updateClickPoint(MouseEvent evt) {
            absolutePoint = new Point(evt.getPoint());
            evt = SwingUtilities.convertMouseEvent(evt.getComponent(), evt, this);
            relativePoint = new Point(evt.getPoint());

            System.out.println(absolutePoint);
            System.out.println(relativePoint);

            repaint();
        }

        protected void paintCross(Graphics2D g2d, Point p) {
            g2d.drawLine(p.x - 5, p.y - 5, p.x + 5, p.y + 5);
            g2d.drawLine(p.x - 5, p.y + 5, p.x + 5, p.y - 5);
        }

        /*
         * This is not recommended, but I want to paint ontop of everything...
         */
        @Override
        public void paint(Graphics g) {
            super.paint(g);

            Graphics2D g2d = (Graphics2D) g;

            if (relativePoint != null) {
                g2d.setColor(Color.BLACK);
                paintCross(g2d, relativePoint);
            }

            if (absolutePoint != null) {
                g2d.setColor(Color.RED);
                paintCross(g2d, absolutePoint);
            }

        }
    }

    protected class MousePane extends JPanel {

        private Point clickPoint;

        public MousePane() {

            addMouseListener(new MouseAdapter() {

                @Override
                public void mouseClicked(MouseEvent e) {
                    clickPoint = e.getPoint();
                    TestMouseClickPoint.this.updateClickPoint(e);
                    repaint();
                }
            });

            setBorder(new LineBorder(Color.RED));

        }

        @Override
        protected void paintComponent(Graphics g) {

            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g;
            g2d.setColor(Color.BLUE);

            if (clickPoint != null) {
                g2d.drawLine(clickPoint.x, clickPoint.y - 5, clickPoint.x, clickPoint.y + 5);
                g2d.drawLine(clickPoint.x - 5, clickPoint.y, clickPoint.x + 5, clickPoint.y);
            }

        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException ex) {
        } catch (InstantiationException ex) {
        } catch (IllegalAccessException ex) {
        } catch (UnsupportedLookAndFeelException ex) {
        }

        new TestMouseClickPoint().setVisible(true);
    }
}

Basically, it will paint three points. The point that the mouse was clicked (relative to the source of the event), the unconverted point in the parent container and the converted point with the parent container.

The next thing you need to do is determine the mouse location is actually been converted, failing that. I'd probably need to see a working example of your code to determine what it is you're actually doing.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!