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

Posted

技术标签:

【中文标题】如何保持鼠标相对于屏幕的位置并忽略组件旋转?【英文标题】:How to keep mouse position relative to screen and disregard component rotation? 【发布时间】:2017-12-06 04:00:03 【问题描述】:

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

我提供了一张图片来说明我所了解的更多内容。黑框代表一个形状供参考,紫框位于鼠标坐标上。 Rotation example image

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

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

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

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

        
    

【问题讨论】:

java.awt.Robot?计算紫色方块的新位置是一个简单的几何坐标变换,然后将鼠标移动到新坐标。坐标变换是一个与编程无关的纯几何问题,参考信息在网上很多地方都可以找到。 @JimGarrison 我已经尝试实现一个基本的机器人,但我最终得到了相同的结果。知道如何用机器人做到这一点吗?我对此很陌生,抱歉 【参考方案1】:

鼠标位置以绝对值报告,但方框图是经过变换的。您需要对鼠标位置进行逆变换以使其回到指针。

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

【讨论】:

以上是关于如何保持鼠标相对于屏幕的位置并忽略组件旋转?的主要内容,如果未能解决你的问题,请参考以下文章

获取鼠标点相对于各屏幕窗体和当前控件的位置

原生JS中获取位置的方案总结

原生JS中获取位置的方案总结

在 THREE.js 中获取鼠标相对于 3D 空间的坐标

如何在javascript中获取鼠标相对于窗口视口的位置?

如何获取鼠标位置和缓冲区?