MouseEvent getX 和 getY 与实际坐标的偏移量

MouseEvent getX and getY offset from actual coordinate

我正在编写一个基本的绘画程序,但我一直在使用 RectangleEllipse 工具时遇到问题。如果您单击并拖动,您应该能够使用基于 startpointendpoint 的尺寸绘制形状(均使用 getX()getY()),问题在于这两个形状使 startpoint 正确,但 endpoint 在 x 和 y 坐标中均有偏移。

除了分别将 Line2DRectangle2DEllipse2D 交换之外,下面的代码与我在直线工具中使用的代码(工作正常)几乎相同。

package tools;

import gui.DrawingPanel;

import java.awt.event.ActionEvent;

import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;


/**
 * Creates the Rectangle Action.
 *@version 1
 */
public class RectangleAction extends AbstractAction {

    private final DrawingPanel myPanel;

    private Rectangle2D.Double myRectangle;
    private double Start_X;
    private double Start_Y;

    /**
     * Constructor for Rectangle Action.
     */
    public RectangleAction(final DrawingPanel thePanel) {
        super("Rectangle", getImageIcon()); 

        myPanel = thePanel;
        putValue(Action.MNEMONIC_KEY, KeyEvent.VK_R);
        putValue(Action.SELECTED_KEY, true);
    }

    @Override
    public void actionPerformed(final ActionEvent theEvent) {

        myPanel.addMouseListener(new MyMouseListener());
        myPanel.addMouseMotionListener(new MyMouseListener());

    }

    /**
     * gets the image icon of the action.
     * @return the image icon.
     */
    public static ImageIcon getImageIcon() {
        return new ImageIcon("./images/rectangle.gif");
    }    


    /**
     * Listens for mouse clicks, to draw on our panel.
     */
    private class MyMouseListener extends MouseAdapter {


        private double myX2;
        private double myY2;               


        /**
         * Handles a click event.
         * 
         * @param theEvent The event.
         */
        @Override
        public void mousePressed(final MouseEvent theEvent) {


            Start_X = (double) theEvent.getX();
            Start_Y = (double) theEvent.getY();
        }

        /**
         * Handles the release event.
         * 
         * @param theEvent The event.
         */
        @Override
        public void mouseReleased(final MouseEvent theEvent) {

            myX2 = (double) theEvent.getX();
            myY2 = (double) theEvent.getY();

            myRectangle = new Rectangle2D.Double(Start_X, Start_Y, myX2, myY2);

            myPanel.setShape(myRectangle);
            myPanel.repaint();           

        }

        /**
         * Handles a click event.
         * 
         * @param theEvent The event.
         */
        @Override
        public void mouseDragged(final MouseEvent theEvent) {

            myX2 = (double) theEvent.getX();
            myY2 = (double) theEvent.getY();

            myRectangle = new Rectangle2D.Double(Start_X, Start_Y, myX2, myY2);                                                                                          

            myPanel.setShape(myRectangle);
            myPanel.repaint();           

        }

    }

}

我应该注意,我确实看过 this similar question,但它没有给我想要的答案; DrawingPanel 也只是一个 JPanel,带有一个用于绘制形状的 Paint 组件,仅此而已。

您正在使用释放的 x 和 y 而不是宽度和高度来初始化矩形。

替换

myRectangle = new Rectangle2D.Double(Start_X, Start_Y, myX2, myY2);

        int x;
        int y;
        if (Start_X > myX2) {
            x = myX2;
        } else {
            x = Start_X;
        }
        if (Start_Y > myY2) {
            y = myY2;
        } else {
            y = Start_Y;
        }
        myRectangle = new Rectangle2D.Double(x, y, Math.abs(myX2 - Start_X), Math.abs(myY2 - Start_Y));
myRectangle = new Rectangle2D.Double(Start_X, Start_Y, myX2, myY2);

参数是(x, y, width, height) 你试图指定两个点。

您的绘画逻辑假定您始终将鼠标从 top/left 拖动到 bottom/right。当您根据两个点计算 width/height 时,总是可能会出现鼠标向上和向左拖动的情况,这会导致负值。

这是我用来正确计算矩形边界的代码:

int x = Math.min(startPoint.x, e.getX());
int y = Math.min(startPoint.y, e.getY());
int width = Math.abs(startPoint.x - e.getX());
int height = Math.abs(startPoint.y - e.getY());

您不需要创建两个侦听器,您可以共享同一个侦听器:

//myPanel.addMouseListener(new MyMouseListener());
//myPanel.addMouseMotionListener(new MyMouseListener());
MouseAdapter myMouseAdapter = new MyMouseListener();
myPanel.addMouseListener( myMouseAdapter );
myPanel.addMouseMotionListener( myMouseAdapter);

此外,每次单击按钮时,您都会继续将适配器添加到面板。所以如果你点击你的线条工具,然后是椭圆工具,然后是矩形工具,你就会有 3 个监听器添加到面板中。我建议您在为当前工具添加侦听器之前从面板中删除所有侦听器。