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

时间:2017-12-06 04:00:03

标签: java swing rotation mouse affinetransform

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

我提供了一张图片来说明我所获得的更多内容。黑框表示供参考的形状,紫色框表示鼠标坐标。 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();
            }

        }
    }

1 个答案:

答案 0 :(得分:3)

鼠标位置以绝对值报告,但框图在变换后。您需要对鼠标位置执行逆变换以将其带回指针。

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