如何保持鼠标相对于屏幕的位置并忽略组件旋转?

How to keep mouse position relative to screen and disregard component rotation?

当旋转应用于 Canvas 时,如何旋转鼠标坐标系?当我旋转 Canvas 时,鼠标相对于旋转的组件保持在相同的位置。我想让鼠标坐标考虑组件的旋转,而不是坐标是相对于 window 的位置,而不考虑旋转。

我提供了一张图片来说明我的意思。黑色方框代表参考形状,紫色方框位于鼠标坐标上。 Rotation example image

最左边的图片 - 未旋转 Canvas 中间图片 - 旋转 Canvas Java 看到的 最右边的图片 - 期望的结果

我的示例代码模拟了一个 Canvas,它通过按向左或向右箭头键来旋转。此模拟显示鼠标如何保持在相对于旋转组件的位置,而不是相对于我在屏幕上的鼠标的位置。

有没有办法转换或计算这些新坐标(显示在最右边的图像中),以便它们在 window 中锁定在我的鼠标上,而不考虑旋转?

 package rotation;

    import java.awt.Canvas;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.MouseInfo;
    import java.awt.Point;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.awt.geom.AffineTransform;
    import java.awt.image.BufferStrategy;

    import javax.swing.JFrame;

    @SuppressWarnings("serial")
    public class RotationExample extends Canvas implements Runnable{

        boolean isRunning = false;
        boolean left = false;
        boolean right = false;
        AffineTransform transform = new AffineTransform();
        double rotation = 0.0d;

        public RotationExample() {
            //Create jframe
            JFrame f = new JFrame();
            f.setSize(500, 500);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.setResizable(false);
            f.setUndecorated(true);

            //Add key listener
            this.addKeyListener(new KeyAdapter() {
                public void keyPressed(KeyEvent e) {
                    int k = e.getKeyCode();
                    //Set left and right variables
                    if(k == KeyEvent.VK_LEFT) left = true;
                    if(k == KeyEvent.VK_RIGHT) right = true;
                }

                public void keyReleased(KeyEvent e) {
                    int k = e.getKeyCode();
                    if(k == KeyEvent.VK_LEFT) left = false;
                    if(k == KeyEvent.VK_RIGHT) right = false;
                }
            });

            f.add(this);
            f.setVisible(true);
            start();
        }

        public void render() {
            BufferStrategy bs = this.getBufferStrategy();
            if(bs == null){
                this.createBufferStrategy(3);
                return;
            }

            Graphics g = bs.getDrawGraphics();
            Graphics2D gt = (Graphics2D) g;

            gt.setTransform(transform);

            gt.clearRect(0, 0, 500, 500);

            //Increment rotation based on left or right variables
            if(left) rotation += 0.001;
            else if(right) rotation -= 0.001;

            //Rotate around middle of frame
            gt.rotate(rotation, 250, 250);

            //Draw black rectangle in middle
            gt.setColor(Color.BLACK);
            gt.fillRect(175, 175, 150, 150);

            //Draw red up arrow
            gt.setColor(Color.RED);
            gt.fillPolygon(new int[] {250, 300, 270, 270, 230, 230, 200}, new int[] {200, 250, 250, 300, 300, 250, 250}, 7);

            //Draw rectangle at mouse coordinates
            gt.setColor(Color.MAGENTA);
            Point m = MouseInfo.getPointerInfo().getLocation();
            gt.fillRect((int) m.getX() - 8, (int) m.getY() - 8, 16, 16);

            bs.show();
            gt.dispose();
        }

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

        public void start() {
            isRunning = true;
            new Thread(this).start();
        }

        public void run() {
            //Continuous rendering
            while(isRunning) {
                render();
            }

        }
    }

报告的是绝对鼠标位置,但盒图是变换后的。您需要对鼠标位置进行逆变换以使其返回到指针。

        //Draw rectangle at mouse coordinates
        gt.setColor(Color.MAGENTA);
        Point m = MouseInfo.getPointerInfo().getLocation();
        try {
            gt.getTransform().createInverse().transform(m, m);
            gt.fillRect((int) m.getX() - 8, (int) m.getY() - 8, 16, 16);
        } catch (java.awt.geom.NoninvertibleTransformException e) {
            System.err.println(e);
        }