java - 用鼠标旋转矩形不一致

标签 java swing rotation awt

以下示例绘制 2 个矩形。

在paintComponent()方法中,第一个矩形被正常绘制,第二个矩形被旋转。

旋转基于鼠标移动。如果鼠标点击矩形然后移动 以圆形方式,第二个矩形按预期旋转,但当鼠标旋转时,矩形的旋转并不总是与鼠标同步。

我怀疑这都与角度计算有关。关于如何使矩形的旋转与鼠标移动同步有什么建议吗?

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.util.Vector;

import javax.swing.JComponent;
import javax.swing.JFrame;


public class SimpleTest extends JComponent 
{
    static int x = 200,y = 200 , width = 100 , height = 30;
    static Vector objectsToDraw = new Vector();
    static int mouseClickX, mouseClickY, mouseX, mouseY = 0;
    static double angle;

    public static void main(String[] args) 
    {
        //Create Frame
        JFrame window = new JFrame();

        //Attach Mouse Listeners.
        window.addMouseMotionListener(new MouseMotionListener()
        {
            @Override
            public void mouseMoved(MouseEvent e) {  }

            @Override
            public void mouseDragged(MouseEvent e) 
            {
//              System.out.println("Dragged");
                System.out.println("Dragged at X :" + e.getX() + "   Y : " + e.getY());
                calculateAngle(e.getX(), e.getY());
                mouseX = e.getX();
                mouseY = e.getY();
                window.repaint();
            }

        });

        window.addMouseListener(new MouseListener()
        {
            @Override
            public void mouseClicked(MouseEvent arg0) { }

            @Override
            public void mouseEntered(MouseEvent arg0) { }

            @Override
            public void mouseExited(MouseEvent arg0)  {  }

            @Override
            public void mousePressed(MouseEvent e) 
            {
                System.out.println("Pressed at X :" + e.getX() + "   Y : " + e.getY());
                mouseClickX = e.getX();
                mouseClickY = e.getY();
            }

            @Override
            public void mouseReleased(MouseEvent arg0) 
            {
                System.out.println("Released");
                mouseClickX = 0;
                mouseClickY = 0;
                window.repaint();
            }   

        });

        //show Window
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setBounds(30, 30, 800, 800);
        window.getContentPane().add(new SimpleTest());
        window.setVisible(true);

    }

    public static void calculateAngle (int x, int y) 
    {
        int deltaX = x - 250;//Rectangle Center X
        int deltaY = y - 200;//Rectangle Center Y
        angle = Math.toDegrees(Math.atan2(deltaY, deltaX));
        System.out.println("Angle = " + angle);
    }   

    @Override //Works
    public void paintComponent(Graphics g) 
    {
        System.out.println("paintComponent() - using angle : " + angle);
        Graphics2D g2d = (Graphics2D)g;
        AffineTransform old = g2d.getTransform();
        g.drawRect(x,  y,  width,  height);
        g2d.rotate(Math.toRadians(angle), 250, 215); 
        Rectangle rect2 = new Rectangle(200, 200, 100, 30);
        g.drawRect(x,  y,  width,  height);
        g2d.setTransform(old);
    }   
}

最佳答案

首先,您将 MouseListener 添加到了错误组件。不要将其添加到窗口,而是添加到执行绘图的 JComponent。否则,无论菜单栏有多大,或者任何其他改变绘图组件(使用鼠标位置的组件)相对于 JFrame(您的当前获取鼠标位置的组件)。

例如,

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import javax.swing.*;

@SuppressWarnings("serial")
public class SimpleTest2 extends JPanel {
    // avoiding "magic" numbers
    private static final int PREF_W = 500;
    private static final int PREF_H = PREF_W;
    public static final int RECT_X = 200;
    public static final int RECT_Y = RECT_X;
    public static final int RECT_WIDTH = 100;
    public static final int RECT_HEIGHT = 30;

    private double angle;

    private static void createAndShowGui() {
        SimpleTest2 mainPanel = new SimpleTest2();

        JFrame frame = new JFrame("Simple Test 2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();  // let the GUI size itself
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    public SimpleTest2() {
        // using an adapter is a nice clean way of avoiding empty method bodies
        MouseAdapter myMouse = new MouseAdapter() {

            @Override
            public void mouseDragged(MouseEvent e) {
                calculateAngle(e.getX(), e.getY());
                repaint();
            }

            @Override
            public void mousePressed(MouseEvent e) {
                calculateAngle(e.getX(), e.getY());
                repaint();
            }

        };
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);
    }

    public void calculateAngle(int x, int y) {
        // get rid of "magic" numbers
        int deltaX = x - (RECT_X + RECT_WIDTH / 2);// Rectangle Center X
        int deltaY = y - (RECT_Y + RECT_HEIGHT / 2);// Rectangle Center Y
        angle = Math.toDegrees(Math.atan2(deltaY, deltaX));
    }

    @Override
    public Dimension getPreferredSize() {
        // better way to size the drawing component
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);  // ***don't forget this guy***
        Graphics2D g2d = (Graphics2D) g;

        // for smoother rendering
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        AffineTransform old = g2d.getTransform();
        g.drawRect(RECT_X, RECT_Y, RECT_WIDTH, RECT_HEIGHT);
        g2d.rotate(Math.toRadians(angle), 250, 215);
        // Rectangle rect2 = new Rectangle(200, 200, 100, 30);
        g.drawRect(RECT_X, RECT_Y, RECT_WIDTH, RECT_HEIGHT);
        g2d.setTransform(old);
    }
}

关于java - 用鼠标旋转矩形不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59007807/

相关文章:

java - 在 android 中将不透明设置为自定义颜色(setAlpha)

java - 通过 Intent 卸载 Android 应用程序时崩溃

java - 自定义绘画和 Z 顺序 : query re painting order

java.sql.SQLException :[SQLITE_ERROR] SQL error or missing database (near “ID” :syntax error)

c - 在 C 中交换数组的元素

java - 为 SQLite Android 创建一个有用且可扩展的类

java - 如何像这样在 Java 中获取日期和时间 02-Oct-12 12 :58:20 AM

java - JLabel文字乱码

javascript - 间隔旋转

css - 为什么这个 CSS3 旋转动画设置在 Chrome 和 Safari 上不起作用?